~sbeattie/ubuntu/lucid/vnc4/lp556147

« back to all changes in this revision

Viewing changes to unix/xc/programs/xterm/screen.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *      $Xorg: screen.c,v 1.3 2000/08/17 19:55:09 cpqbld Exp $
 
3
 */
 
4
 
 
5
/*
 
6
 * Copyright 1999-2000,2002 by Thomas E. Dickey
 
7
 *
 
8
 *                         All Rights Reserved
 
9
 *
 
10
 * Permission is hereby granted, free of charge, to any person obtaining a
 
11
 * copy of this software and associated documentation files (the
 
12
 * "Software"), to deal in the Software without restriction, including
 
13
 * without limitation the rights to use, copy, modify, merge, publish,
 
14
 * distribute, sublicense, and/or sell copies of the Software, and to
 
15
 * permit persons to whom the Software is furnished to do so, subject to
 
16
 * the following conditions:
 
17
 *
 
18
 * The above copyright notice and this permission notice shall be included
 
19
 * in all copies or substantial portions of the Software.
 
20
 *
 
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
22
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
23
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
24
 * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
 
25
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 
26
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 
27
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
28
 *
 
29
 * Except as contained in this notice, the name(s) of the above copyright
 
30
 * holders shall not be used in advertising or otherwise to promote the
 
31
 * sale, use or other dealings in this Software without prior written
 
32
 * authorization.
 
33
 *
 
34
 *
 
35
 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 
36
 *
 
37
 *                         All Rights Reserved
 
38
 *
 
39
 * Permission to use, copy, modify, and distribute this software and its
 
40
 * documentation for any purpose and without fee is hereby granted,
 
41
 * provided that the above copyright notice appear in all copies and that
 
42
 * both that copyright notice and this permission notice appear in
 
43
 * supporting documentation, and that the name of Digital Equipment
 
44
 * Corporation not be used in advertising or publicity pertaining to
 
45
 * distribution of the software without specific, written prior permission.
 
46
 *
 
47
 *
 
48
 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 
49
 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 
50
 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 
51
 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 
52
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 
53
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 
54
 * SOFTWARE.
 
55
 */
 
56
 
 
57
/* $XFree86: xc/programs/xterm/screen.c,v 3.60 2002/12/27 21:05:23 dickey Exp $ */
 
58
 
 
59
/* screen.c */
 
60
 
 
61
#include <stdio.h>
 
62
#include <xterm.h>
 
63
#include <error.h>
 
64
#include <data.h>
 
65
#include <xcharmouse.h>
 
66
#include <xterm_io.h>
 
67
 
 
68
#include <signal.h>
 
69
 
 
70
/*
 
71
 * Allocates memory for a 2-dimensional array of chars and returns a pointer
 
72
 * thereto.  Each line is formed from a set of char arrays, with an index
 
73
 * (i.e., the ScrnBuf type).  The first pointer in the index is reserved for
 
74
 * per-line flags, and does not point to data.
 
75
 *
 
76
 * After the per-line flags, we have a series of pointers to char arrays:  The
 
77
 * first one is the actual character array, the second one is the attributes,
 
78
 * the third is the foreground and background colors, and the fourth denotes
 
79
 * the character set.
 
80
 *
 
81
 * We store it all as pointers, because of alignment considerations, together
 
82
 * with the intention of being able to change the total number of pointers per
 
83
 * row according to whether the user wants color or not.
 
84
 */
 
85
ScrnBuf
 
86
Allocate(int nrow, int ncol, Char ** addr)
 
87
{
 
88
    ScrnBuf base;
 
89
    Char *tmp;
 
90
    int i, j, k;
 
91
    size_t entries = MAX_PTRS * nrow;
 
92
    size_t length = BUF_PTRS * nrow * ncol;
 
93
 
 
94
    if ((base = (ScrnBuf) calloc(entries, sizeof(char *))) == 0)
 
95
          SysError(ERROR_SCALLOC);
 
96
 
 
97
    if ((tmp = (Char *) calloc(length, sizeof(Char))) == 0)
 
98
        SysError(ERROR_SCALLOC2);
 
99
 
 
100
    *addr = tmp;
 
101
    for (i = k = 0; i < nrow; i++) {
 
102
        base[k] = 0;            /* per-line flags */
 
103
        k += BUF_HEAD;
 
104
        for (j = BUF_HEAD; j < MAX_PTRS; j++) {
 
105
            base[k++] = tmp;
 
106
            tmp += ncol;
 
107
        }
 
108
    }
 
109
 
 
110
    return (base);
 
111
}
 
112
 
 
113
/*
 
114
 *  This is called when the screen is resized.
 
115
 *  Returns the number of lines the text was moved down (neg for up).
 
116
 *  (Return value only necessary with SouthWestGravity.)
 
117
 */
 
118
static int
 
119
Reallocate(ScrnBuf * sbuf,
 
120
           Char ** sbufaddr,
 
121
           int nrow,
 
122
           int ncol,
 
123
           int oldrow,
 
124
           int oldcol)
 
125
{
 
126
    ScrnBuf base;
 
127
    Char *tmp;
 
128
    int i, j, k, minrows;
 
129
    size_t mincols;
 
130
    Char *oldbuf;
 
131
    int move_down = 0, move_up = 0;
 
132
    size_t entries = MAX_PTRS * nrow;
 
133
    size_t length = BUF_PTRS * nrow * ncol;
 
134
 
 
135
    if (sbuf == NULL || *sbuf == NULL) {
 
136
        return 0;
 
137
    }
 
138
 
 
139
    oldbuf = *sbufaddr;
 
140
 
 
141
    /*
 
142
     * Special case if oldcol == ncol - straight forward realloc and
 
143
     * update of the additional lines in sbuf
 
144
     *
 
145
     * FIXME: this is a good idea, but doesn't seem to be implemented.
 
146
     * -gildea
 
147
     */
 
148
 
 
149
    /*
 
150
     * realloc sbuf, the pointers to all the lines.
 
151
     * If the screen shrinks, remove lines off the top of the buffer
 
152
     * if resizeGravity resource says to do so.
 
153
     */
 
154
    if (nrow < oldrow
 
155
        && term->misc.resizeGravity == SouthWestGravity) {
 
156
        /* Remove lines off the top of the buffer if necessary. */
 
157
        move_up = (oldrow - nrow)
 
158
            - (term->screen.max_row - term->screen.cur_row);
 
159
        if (move_up < 0)
 
160
            move_up = 0;
 
161
        /* Overlapping memmove here! */
 
162
        memmove(*sbuf, *sbuf + (move_up * MAX_PTRS),
 
163
                MAX_PTRS * (oldrow - move_up) * sizeof((*sbuf)[0]));
 
164
    }
 
165
    *sbuf = (ScrnBuf) realloc((char *) (*sbuf), entries * sizeof(char *));
 
166
    if (*sbuf == 0)
 
167
        SysError(ERROR_RESIZE);
 
168
    base = *sbuf;
 
169
 
 
170
    /*
 
171
     *  create the new buffer space and copy old buffer contents there
 
172
     *  line by line.
 
173
     */
 
174
    if ((tmp = (Char *) calloc(length, sizeof(Char))) == 0)
 
175
        SysError(ERROR_SREALLOC);
 
176
    *sbufaddr = tmp;
 
177
    minrows = (oldrow < nrow) ? oldrow : nrow;
 
178
    mincols = (oldcol < ncol) ? oldcol : ncol;
 
179
    if (nrow > oldrow
 
180
        && term->misc.resizeGravity == SouthWestGravity) {
 
181
        /* move data down to bottom of expanded screen */
 
182
        move_down = Min(nrow - oldrow, term->screen.savedlines);
 
183
        tmp += (ncol * move_down * BUF_PTRS);
 
184
    }
 
185
 
 
186
    for (i = k = 0; i < minrows; i++) {
 
187
        k += BUF_HEAD;
 
188
        for (j = BUF_HEAD; j < MAX_PTRS; j++) {
 
189
            memcpy(tmp, base[k++], mincols);
 
190
            tmp += ncol;
 
191
        }
 
192
    }
 
193
 
 
194
    /*
 
195
     * update the pointers in sbuf
 
196
     */
 
197
    for (i = k = 0, tmp = *sbufaddr; i < nrow; i++) {
 
198
        for (j = 0; j < BUF_HEAD; j++)
 
199
            base[k++] = 0;
 
200
        for (j = BUF_HEAD; j < MAX_PTRS; j++) {
 
201
            base[k++] = tmp;
 
202
            tmp += ncol;
 
203
        }
 
204
    }
 
205
 
 
206
    /* Now free the old buffer */
 
207
    free(oldbuf);
 
208
 
 
209
    return move_down ? move_down : -move_up;    /* convert to rows */
 
210
}
 
211
 
 
212
int last_written_row = -1;
 
213
int last_written_col = -1;
 
214
 
 
215
/*
 
216
 * Writes str into buf at screen's current row and column.  Characters are set
 
217
 * to match flags.
 
218
 */
 
219
void
 
220
ScreenWrite(TScreen * screen,
 
221
            PAIRED_CHARS(Char * str, Char * str2),
 
222
            unsigned flags,
 
223
            unsigned cur_fg_bg,
 
224
            int len)            /* length of string */
 
225
{
 
226
#if OPT_ISO_COLORS
 
227
#if OPT_EXT_COLORS
 
228
    Char *fbf = 0;
 
229
    Char *fbb = 0;
 
230
#else
 
231
    Char *fb = 0;
 
232
#endif
 
233
#endif
 
234
#if OPT_DEC_CHRSET
 
235
    Char *cb = 0;
 
236
#endif
 
237
    int length = len;           /* workaround for compiler bug? */
 
238
    Char *attrs;
 
239
    int avail = screen->max_col - screen->cur_col + 1;
 
240
    Char *col;
 
241
    int wrappedbit;
 
242
#if OPT_WIDE_CHARS
 
243
    Char starcol, starcol2;
 
244
    Char *comb1l = 0, *comb1h = 0, *comb2l = 0, *comb2h = 0;
 
245
#endif
 
246
 
 
247
#if OPT_WIDE_CHARS
 
248
    int real_width = visual_width(PAIRED_CHARS(str, str2), length);
 
249
#else
 
250
    int real_width = length;
 
251
#endif
 
252
 
 
253
    if (length > avail)
 
254
        length = avail;
 
255
    if (length <= 0)
 
256
        return;
 
257
 
 
258
    col = SCRN_BUF_CHARS(screen, screen->cur_row) + screen->cur_col;
 
259
    attrs = SCRN_BUF_ATTRS(screen, screen->cur_row) + screen->cur_col;
 
260
 
 
261
    if_OPT_WIDE_CHARS(screen, {
 
262
        comb1l = SCRN_BUF_COM1L(screen, screen->cur_row) + screen->cur_col;
 
263
        comb1h = SCRN_BUF_COM1H(screen, screen->cur_row) + screen->cur_col;
 
264
        comb2l = SCRN_BUF_COM2L(screen, screen->cur_row) + screen->cur_col;
 
265
        comb2h = SCRN_BUF_COM2H(screen, screen->cur_row) + screen->cur_col;
 
266
    });
 
267
 
 
268
    if_OPT_EXT_COLORS(screen, {
 
269
        fbf = SCRN_BUF_FGRND(screen, screen->cur_row) + screen->cur_col;
 
270
        fbb = SCRN_BUF_BGRND(screen, screen->cur_row) + screen->cur_col;
 
271
    });
 
272
    if_OPT_ISO_TRADITIONAL_COLORS(screen, {
 
273
        fb = SCRN_BUF_COLOR(screen, screen->cur_row) + screen->cur_col;
 
274
    });
 
275
    if_OPT_DEC_CHRSET({
 
276
        cb = SCRN_BUF_CSETS(screen, screen->cur_row) + screen->cur_col;
 
277
    });
 
278
 
 
279
    wrappedbit = ScrnTstWrapped(screen, screen->cur_row);
 
280
 
 
281
#if OPT_WIDE_CHARS
 
282
    starcol = *col;
 
283
    starcol2 = col[length - 1];
 
284
#endif
 
285
 
 
286
    /* write blanks if we're writing invisible text */
 
287
    if (flags & INVISIBLE) {
 
288
        memset(col, ' ', length);
 
289
    } else {
 
290
        memcpy(col, str, length);       /* This can stand for the present. If it
 
291
                                           is wrong, we will scribble over it */
 
292
    }
 
293
#define ERROR_1 0x20
 
294
#define ERROR_2 0x00
 
295
    if_OPT_WIDE_CHARS(screen, {
 
296
 
 
297
        Char *wc;
 
298
 
 
299
        if (real_width != length) {
 
300
            Char *c = col;
 
301
            wc = SCRN_BUF_WIDEC(screen, screen->cur_row);
 
302
            wc += screen->cur_col;
 
303
            if (screen->cur_col && starcol == HIDDEN_LO && *wc == HIDDEN_HI
 
304
                && iswide(c[-1] | (wc[-1] << 8))) {
 
305
                c[-1] = ERROR_1;
 
306
                wc[-1] = ERROR_2;
 
307
            }
 
308
            /* if we are overwriting the right hand half of a
 
309
               wide character, make the other half vanish */
 
310
            while (length) {
 
311
                int ch = *str;
 
312
                if (str2)
 
313
                    ch |= *str2 << 8;
 
314
 
 
315
                *c = *str;
 
316
                c++;
 
317
                str++;
 
318
 
 
319
                if (str2) {
 
320
                    *wc = *str2;
 
321
                    str2++;
 
322
                } else
 
323
                    *wc = 0;
 
324
                wc++;
 
325
                length--;
 
326
 
 
327
                if (iswide(ch)) {
 
328
                    *c = HIDDEN_LO;
 
329
                    *wc = HIDDEN_HI;
 
330
                    c++;
 
331
                    wc++;
 
332
                }
 
333
            }
 
334
 
 
335
            if (*c == HIDDEN_LO
 
336
                && *wc == HIDDEN_HI
 
337
                && c[-1] == HIDDEN_LO
 
338
                && wc[-1] == HIDDEN_HI) {
 
339
                *c = ERROR_1;
 
340
                *wc = ERROR_2;
 
341
            }
 
342
            /* if we are overwriting the left hand half of a
 
343
               wide character, make the other half vanish */
 
344
        }
 
345
 
 
346
        else {
 
347
 
 
348
            if ((wc = SCRN_BUF_WIDEC(screen, screen->cur_row)) != 0) {
 
349
                wc += screen->cur_col;
 
350
                if (screen->cur_col && starcol == HIDDEN_LO && *wc == HIDDEN_HI
 
351
                    && iswide(col[-1] | (wc[-1] << 8))) {
 
352
                    col[-1] = ERROR_1;
 
353
                    wc[-1] = ERROR_2;
 
354
                }
 
355
                /* if we are overwriting the right hand half of a
 
356
                   wide character, make the other half vanish */
 
357
                if (col[length] == HIDDEN_LO && wc[length] == HIDDEN_HI &&
 
358
                    iswide(starcol2 | (wc[length - 1] << 8))) {
 
359
                    col[length] = ERROR_1;
 
360
                    wc[length] = ERROR_2;
 
361
                }
 
362
                /* if we are overwriting the left hand half of a
 
363
                   wide character, make the other half vanish */
 
364
                if ((flags & INVISIBLE) || (str2 == 0))
 
365
                    memset(wc, 0, length);
 
366
                else
 
367
                    memcpy(wc, str2, length);
 
368
            }
 
369
        }
 
370
    });
 
371
 
 
372
    flags &= ATTRIBUTES;
 
373
    flags |= CHARDRAWN;
 
374
    memset(attrs, flags, real_width);
 
375
 
 
376
    if_OPT_WIDE_CHARS(screen, {
 
377
        memset(comb1l, 0, real_width);
 
378
        memset(comb2l, 0, real_width);
 
379
        memset(comb1h, 0, real_width);
 
380
        memset(comb2h, 0, real_width);
 
381
    });
 
382
    if_OPT_EXT_COLORS(screen, {
 
383
        memset(fbf, cur_fg_bg >> 8, real_width);
 
384
        memset(fbb, cur_fg_bg & 0xff, real_width);
 
385
    });
 
386
    if_OPT_ISO_TRADITIONAL_COLORS(screen, {
 
387
        memset(fb, cur_fg_bg, real_width);
 
388
    });
 
389
    if_OPT_DEC_CHRSET({
 
390
        memset(cb, curXtermChrSet(screen->cur_row), real_width);
 
391
    });
 
392
 
 
393
    if (wrappedbit)
 
394
        ScrnSetWrapped(screen, screen->cur_row);
 
395
    else
 
396
        ScrnClrWrapped(screen, screen->cur_row);
 
397
 
 
398
    last_written_col = screen->cur_col + real_width - 1;
 
399
    last_written_row = screen->cur_row;
 
400
 
 
401
    if_OPT_XMC_GLITCH(screen, {
 
402
        Resolve_XMC(screen);
 
403
    });
 
404
}
 
405
 
 
406
/*
 
407
 * Saves pointers to the n lines beginning at sb + where, and clears the lines
 
408
 */
 
409
static void
 
410
ScrnClearLines(TScreen * screen, ScrnBuf sb, int where, int n, int size)
 
411
{
 
412
    int i, j;
 
413
    size_t len = ScrnPointers(screen, n);
 
414
    int last = (n * MAX_PTRS);
 
415
 
 
416
    /* save n lines at where */
 
417
    memcpy((char *) screen->save_ptr,
 
418
           (char *) &sb[MAX_PTRS * where],
 
419
           len);
 
420
 
 
421
    /* clear contents of old rows */
 
422
    if (TERM_COLOR_FLAGS) {
 
423
        int flags = TERM_COLOR_FLAGS;
 
424
        for (i = 0; i < last; i += MAX_PTRS) {
 
425
            for (j = 0; j < MAX_PTRS; j++) {
 
426
                if (j < BUF_HEAD)
 
427
                    screen->save_ptr[i + j] = 0;
 
428
                else if (j == OFF_ATTRS)
 
429
                    memset(screen->save_ptr[i + j], flags, size);
 
430
#if OPT_ISO_COLORS
 
431
#if OPT_EXT_COLORS
 
432
                else if (j == OFF_FGRND)
 
433
                    memset(screen->save_ptr[i + j], term->sgr_foreground, size);
 
434
                else if (j == OFF_BGRND)
 
435
                    memset(screen->save_ptr[i + j], term->cur_background, size);
 
436
#else
 
437
                else if (j == OFF_COLOR)
 
438
                    memset(screen->save_ptr[i + j], xtermColorPair(), size);
 
439
#endif
 
440
#endif
 
441
                else
 
442
                    bzero(screen->save_ptr[i + j], size);
 
443
            }
 
444
        }
 
445
    } else {
 
446
        for (i = 0; i < last; i += MAX_PTRS) {
 
447
            for (j = 0; j < BUF_HEAD; j++)
 
448
                screen->save_ptr[i + j] = 0;
 
449
            for (j = BUF_HEAD; j < MAX_PTRS; j++)
 
450
                bzero(screen->save_ptr[i + j], size);
 
451
        }
 
452
    }
 
453
}
 
454
 
 
455
size_t
 
456
ScrnPointers(TScreen * screen, size_t len)
 
457
{
 
458
    len *= (MAX_PTRS * sizeof(Char *));
 
459
 
 
460
    if (len > screen->save_len) {
 
461
        if (screen->save_len)
 
462
            screen->save_ptr = (Char **) realloc(screen->save_ptr, len);
 
463
        else
 
464
            screen->save_ptr = (Char **) malloc(len);
 
465
        screen->save_len = len;
 
466
        if (screen->save_ptr == 0)
 
467
            SysError(ERROR_SAVE_PTR);
 
468
    }
 
469
    return len;
 
470
}
 
471
 
 
472
/*
 
473
 * Inserts n blank lines at sb + where, treating last as a bottom margin.
 
474
 * Size is the size of each entry in sb.
 
475
 * Requires: 0 <= where < where + n <= last
 
476
 */
 
477
void
 
478
ScrnInsertLine(TScreen * screen, ScrnBuf sb, int last, int where, int n, int size)
 
479
{
 
480
    size_t len = ScrnPointers(screen, n);
 
481
 
 
482
    /* save n lines at bottom */
 
483
    ScrnClearLines(screen, sb, (last -= n - 1), n, size);
 
484
 
 
485
    /*
 
486
     * WARNING, overlapping copy operation.  Move down lines (pointers).
 
487
     *
 
488
     *   +----|---------|--------+
 
489
     *
 
490
     * is copied in the array to:
 
491
     *
 
492
     *   +--------|---------|----+
 
493
     */
 
494
    memmove((char *) &sb[MAX_PTRS * (where + n)],
 
495
            (char *) &sb[MAX_PTRS * where],
 
496
            MAX_PTRS * sizeof(char *) * (last - where));
 
497
 
 
498
    /* reuse storage for new lines at where */
 
499
    memcpy((char *) &sb[MAX_PTRS * where],
 
500
           (char *) screen->save_ptr,
 
501
           len);
 
502
}
 
503
 
 
504
/*
 
505
 * Deletes n lines at sb + where, treating last as a bottom margin.
 
506
 * Size is the size of each entry in sb.
 
507
 * Requires 0 <= where < where + n < = last
 
508
 */
 
509
void
 
510
ScrnDeleteLine(TScreen * screen, ScrnBuf sb, int last, int where, int n, int size)
 
511
{
 
512
    ScrnClearLines(screen, sb, where, n, size);
 
513
 
 
514
    /* move up lines */
 
515
    memmove((char *) &sb[MAX_PTRS * where],
 
516
            (char *) &sb[MAX_PTRS * (where + n)],
 
517
            MAX_PTRS * sizeof(char *) * ((last -= n - 1) - where));
 
518
 
 
519
    /* reuse storage for new bottom lines */
 
520
    memcpy((char *) &sb[MAX_PTRS * last],
 
521
           (char *) screen->save_ptr,
 
522
           MAX_PTRS * sizeof(char *) * n);
 
523
}
 
524
 
 
525
/*
 
526
 * Inserts n blanks in screen at current row, col.  Size is the size of each
 
527
 * row.
 
528
 */
 
529
void
 
530
ScrnInsertChar(TScreen * screen, int n)
 
531
{
 
532
    ScrnBuf sb = screen->visbuf;
 
533
    int size = screen->max_col + 1;
 
534
    int row = screen->cur_row;
 
535
    int col = screen->cur_col;
 
536
    int i, j;
 
537
    Char *ptr = BUF_CHARS(sb, row);
 
538
    Char *attrs = BUF_ATTRS(sb, row);
 
539
    int wrappedbit = ScrnTstWrapped(screen, row);
 
540
    int flags = CHARDRAWN | TERM_COLOR_FLAGS;
 
541
    size_t nbytes;
 
542
 
 
543
    if (size - (col + n) <= 0) {
 
544
        if ((n = size - col) <= 0) {
 
545
            return;
 
546
        }
 
547
    }
 
548
    nbytes = (size - (col + n));
 
549
 
 
550
    ScrnClrWrapped(screen, row);        /* make sure the bit isn't moved */
 
551
    for (i = size - 1; i >= col + n; i--) {
 
552
        ptr[i] = ptr[j = i - n];
 
553
        attrs[i] = attrs[j];
 
554
    }
 
555
 
 
556
    for (i = col; i < col + n; i++)
 
557
        ptr[i] = ' ';
 
558
    for (i = col; i < col + n; i++)
 
559
        attrs[i] = flags;
 
560
    if_OPT_EXT_COLORS(screen, {
 
561
        ptr = BUF_FGRND(sb, row);
 
562
        memmove(ptr + col + n, ptr + col, nbytes);
 
563
        memset(ptr + col, term->sgr_foreground, n);
 
564
        ptr = BUF_BGRND(sb, row);
 
565
        memmove(ptr + col + n, ptr + col, nbytes);
 
566
        memset(ptr + col, term->cur_background, n);
 
567
    });
 
568
    if_OPT_ISO_TRADITIONAL_COLORS(screen, {
 
569
        ptr = BUF_COLOR(sb, row);
 
570
        memmove(ptr + col + n, ptr + col, nbytes);
 
571
        memset(ptr + col, xtermColorPair(), n);
 
572
    });
 
573
    if_OPT_DEC_CHRSET({
 
574
        ptr = BUF_CSETS(sb, row);
 
575
        memmove(ptr + col + n, ptr + col, nbytes);
 
576
        memset(ptr + col, curXtermChrSet(row), n);
 
577
    });
 
578
    if_OPT_WIDE_CHARS(screen, {
 
579
        ptr = BUF_WIDEC(sb, row);
 
580
        memmove(ptr + col + n, ptr + col, nbytes);
 
581
        memset(ptr + col, 0, n);
 
582
 
 
583
        ptr = BUF_COM1L(sb, row);
 
584
        memmove(ptr + col + n, ptr + col, nbytes);
 
585
        memset(ptr + col, 0, n);
 
586
 
 
587
        ptr = BUF_COM1H(sb, row);
 
588
        memmove(ptr + col + n, ptr + col, nbytes);
 
589
        memset(ptr + col, 0, n);
 
590
 
 
591
        ptr = BUF_COM2L(sb, row);
 
592
        memmove(ptr + col + n, ptr + col, nbytes);
 
593
        memset(ptr + col, 0, n);
 
594
 
 
595
        ptr = BUF_COM2H(sb, row);
 
596
        memmove(ptr + col + n, ptr + col, nbytes);
 
597
        memset(ptr + col, 0, n);
 
598
    });
 
599
 
 
600
    if (wrappedbit)
 
601
        ScrnSetWrapped(screen, row);
 
602
    else
 
603
        ScrnClrWrapped(screen, row);
 
604
}
 
605
 
 
606
/*
 
607
 * Deletes n characters at current row, col.
 
608
 */
 
609
void
 
610
ScrnDeleteChar(TScreen * screen, int n)
 
611
{
 
612
    ScrnBuf sb = screen->visbuf;
 
613
    int size = screen->max_col + 1;
 
614
    int row = screen->cur_row;
 
615
    int col = screen->cur_col;
 
616
    Char *ptr = BUF_CHARS(sb, row);
 
617
    Char *attrs = BUF_ATTRS(sb, row);
 
618
    size_t nbytes;
 
619
 
 
620
    if (size - (col + n) <= 0) {
 
621
        if ((n = size - col) <= 0) {
 
622
            return;
 
623
        }
 
624
    }
 
625
    nbytes = (size - (col + n));
 
626
 
 
627
    memmove(ptr + col, ptr + col + n, nbytes);
 
628
    memmove(attrs + col, attrs + col + n, nbytes);
 
629
    bzero(ptr + size - n, n);
 
630
    memset(attrs + size - n, TERM_COLOR_FLAGS, n);
 
631
 
 
632
    if_OPT_EXT_COLORS(screen, {
 
633
        ptr = BUF_FGRND(sb, row);
 
634
        memmove(ptr + col, ptr + col + n, nbytes);
 
635
        memset(ptr + size - n, term->sgr_foreground, n);
 
636
        ptr = BUF_BGRND(sb, row);
 
637
        memmove(ptr + col, ptr + col + n, nbytes);
 
638
        memset(ptr + size - n, term->cur_background, n);
 
639
    });
 
640
    if_OPT_ISO_TRADITIONAL_COLORS(screen, {
 
641
        ptr = BUF_COLOR(sb, row);
 
642
        memmove(ptr + col, ptr + col + n, nbytes);
 
643
        memset(ptr + size - n, xtermColorPair(), n);
 
644
    });
 
645
    if_OPT_DEC_CHRSET({
 
646
        ptr = BUF_CSETS(sb, row);
 
647
        memmove(ptr + col, ptr + col + n, nbytes);
 
648
        memset(ptr + size - n, curXtermChrSet(row), n);
 
649
    });
 
650
    if_OPT_WIDE_CHARS(screen, {
 
651
        ptr = BUF_WIDEC(sb, row);
 
652
        memmove(ptr + col, ptr + col + n, nbytes);
 
653
        memset(ptr + size - n, 0, n);
 
654
 
 
655
        ptr = BUF_COM1L(sb, row);
 
656
        memmove(ptr + col, ptr + col + n, nbytes);
 
657
        memset(ptr + size - n, 0, n);
 
658
 
 
659
        ptr = BUF_COM1H(sb, row);
 
660
        memmove(ptr + col, ptr + col + n, nbytes);
 
661
        memset(ptr + size - n, 0, n);
 
662
 
 
663
        ptr = BUF_COM2L(sb, row);
 
664
        memmove(ptr + col, ptr + col + n, nbytes);
 
665
        memset(ptr + size - n, 0, n);
 
666
 
 
667
        ptr = BUF_COM2H(sb, row);
 
668
        memmove(ptr + col, ptr + col + n, nbytes);
 
669
        memset(ptr + size - n, 0, n);
 
670
    });
 
671
    ScrnClrWrapped(screen, row);
 
672
}
 
673
 
 
674
/*
 
675
 * Repaints the area enclosed by the parameters.
 
676
 * Requires: (toprow, leftcol), (toprow + nrows, leftcol + ncols) are
 
677
 *           coordinates of characters in screen;
 
678
 *           nrows and ncols positive.
 
679
 *           all dimensions are based on single-characters.
 
680
 */
 
681
void
 
682
ScrnRefresh(TScreen * screen,
 
683
            int toprow,
 
684
            int leftcol,
 
685
            int nrows,
 
686
            int ncols,
 
687
            Bool force)         /* ... leading/trailing spaces */
 
688
{
 
689
    int y = toprow * FontHeight(screen) + screen->border;
 
690
    int row;
 
691
    int topline = screen->topline;
 
692
    int maxrow = toprow + nrows - 1;
 
693
    int scrollamt = screen->scroll_amt;
 
694
    int max = screen->max_row;
 
695
    int gc_changes = 0;
 
696
#ifdef __CYGWIN__
 
697
    static char first_time = 1;
 
698
#endif
 
699
    static int recurse = 0;
 
700
 
 
701
    TRACE(("ScrnRefresh (%d,%d) - (%d,%d)%s\n",
 
702
           toprow, leftcol,
 
703
           nrows, ncols,
 
704
           force ? " force" : ""));
 
705
 
 
706
    if (screen->cursor_col >= leftcol
 
707
        && screen->cursor_col <= (leftcol + ncols - 1)
 
708
        && screen->cursor_row >= toprow + topline
 
709
        && screen->cursor_row <= maxrow + topline)
 
710
        screen->cursor_state = OFF;
 
711
 
 
712
    for (row = toprow; row <= maxrow; y += FontHeight(screen), row++) {
 
713
#if OPT_ISO_COLORS
 
714
#if OPT_EXT_COLORS
 
715
        Char *fbf = 0;
 
716
        Char *fbb = 0;
 
717
#define ColorOf(col) ((fbf[col] << 8) | fbb[col])
 
718
#else
 
719
        Char *fb = 0;
 
720
#define ColorOf(col) (fb[col])
 
721
#endif
 
722
#endif
 
723
#if OPT_DEC_CHRSET
 
724
        Char *cb = 0;
 
725
#endif
 
726
#if OPT_WIDE_CHARS
 
727
        int wideness = 0;
 
728
        Char *widec = 0;
 
729
#define WIDEC_PTR(cell) widec ? &widec[cell] : 0
 
730
#endif
 
731
        Char cs = 0;
 
732
        Char *chars;
 
733
        Char *attrs;
 
734
        int col = leftcol;
 
735
        int maxcol = leftcol + ncols - 1;
 
736
        int hi_col = maxcol;
 
737
        int lastind;
 
738
        int flags;
 
739
        int test;
 
740
        int fg_bg = 0, fg = 0, bg = 0;
 
741
        int x;
 
742
        GC gc;
 
743
        Boolean hilite;
 
744
 
 
745
        if (row < screen->top_marg || row > screen->bot_marg)
 
746
            lastind = row;
 
747
        else
 
748
            lastind = row - scrollamt;
 
749
 
 
750
        TRACE(("ScrnRefresh row=%d lastind=%d/%d\n", row, lastind, max));
 
751
        if (lastind < 0 || lastind > max)
 
752
            continue;
 
753
 
 
754
        chars = SCRN_BUF_CHARS(screen, lastind + topline);
 
755
        attrs = SCRN_BUF_ATTRS(screen, lastind + topline);
 
756
 
 
757
        if_OPT_DEC_CHRSET({
 
758
            cb = SCRN_BUF_CSETS(screen, lastind + topline);
 
759
        });
 
760
 
 
761
        if_OPT_WIDE_CHARS(screen, {
 
762
            widec = SCRN_BUF_WIDEC(screen, lastind + topline);
 
763
        });
 
764
 
 
765
        if_OPT_WIDE_CHARS(screen, {
 
766
            /* This fixes an infinite recursion bug, that leads
 
767
               to display anomalies. It seems to be related to 
 
768
               problems with the selection. */
 
769
            if (recurse < 3) {
 
770
                /* adjust to redraw all of a widechar if we just wanted 
 
771
                   to draw the right hand half */
 
772
                if (iswide(chars[leftcol - 1] | (widec[leftcol - 1] << 8)) &&
 
773
                    (chars[leftcol] | (widec[leftcol] << 8)) == HIDDEN_CHAR) {
 
774
                    leftcol--;
 
775
                    ncols++;
 
776
                    col = leftcol;
 
777
                }
 
778
            } else {
 
779
                fprintf(stderr, "This should not happen. Why is it so?\n");
 
780
            }
 
781
        });
 
782
 
 
783
        if (row < screen->startHRow || row > screen->endHRow ||
 
784
            (row == screen->startHRow && maxcol < screen->startHCol) ||
 
785
            (row == screen->endHRow && col >= screen->endHCol)) {
 
786
#if OPT_DEC_CHRSET
 
787
            /*
 
788
             * Temporarily change dimensions to double-sized characters so
 
789
             * we can reuse the recursion on this function.
 
790
             */
 
791
            if (CSET_DOUBLE(*cb)) {
 
792
                col /= 2;
 
793
                maxcol /= 2;
 
794
            }
 
795
#endif
 
796
            /* row does not intersect selection; don't hilite */
 
797
            if (!force) {
 
798
                while (col <= maxcol && (attrs[col] & ~BOLD) == 0 &&
 
799
                       (chars[col] & ~040) == 0)
 
800
                    col++;
 
801
 
 
802
                while (col <= maxcol && (attrs[maxcol] & ~BOLD) == 0 &&
 
803
                       (chars[maxcol] & ~040) == 0)
 
804
                    maxcol--;
 
805
            }
 
806
#if OPT_DEC_CHRSET
 
807
            if (CSET_DOUBLE(*cb)) {
 
808
                col *= 2;
 
809
                maxcol *= 2;
 
810
            }
 
811
#endif
 
812
            hilite = False;
 
813
        } else {
 
814
            /* row intersects selection; split into pieces of single type */
 
815
            if (row == screen->startHRow && col < screen->startHCol) {
 
816
                recurse++;
 
817
                ScrnRefresh(screen, row, col, 1, screen->startHCol - col,
 
818
                            force);
 
819
                col = screen->startHCol;
 
820
            }
 
821
            if (row == screen->endHRow && maxcol >= screen->endHCol) {
 
822
                recurse++;
 
823
                ScrnRefresh(screen, row, screen->endHCol, 1,
 
824
                            maxcol - screen->endHCol + 1, force);
 
825
                maxcol = screen->endHCol - 1;
 
826
            }
 
827
 
 
828
            /*
 
829
             * If we're highlighting because the user is doing cut/paste,
 
830
             * trim the trailing blanks from the highlighted region so we're
 
831
             * showing the actual extent of the text that'll be cut.  If
 
832
             * we're selecting a blank line, we'll highlight one column
 
833
             * anyway.
 
834
             *
 
835
             * We don't do this if the mouse-hilite mode is set because that
 
836
             * would be too confusing.
 
837
             *
 
838
             * The default if the highlightSelection resource isn't set will
 
839
             * highlight the whole width of the terminal, which is easy to
 
840
             * see, but harder to use (because trailing blanks aren't as
 
841
             * apparent).
 
842
             */
 
843
            if (screen->highlight_selection
 
844
                && screen->send_mouse_pos != VT200_HIGHLIGHT_MOUSE) {
 
845
                hi_col = screen->max_col;
 
846
                while (hi_col > 0 && !(attrs[hi_col] & CHARDRAWN))
 
847
                    hi_col--;
 
848
            }
 
849
 
 
850
            /* remaining piece should be hilited */
 
851
            hilite = True;
 
852
        }
 
853
 
 
854
        if (col > maxcol)
 
855
            continue;
 
856
 
 
857
        /*
 
858
         * Go back to double-sized character dimensions if the line has
 
859
         * double-width characters.  Note that 'hi_col' is already in the
 
860
         * right units.
 
861
         */
 
862
        if_OPT_DEC_CHRSET({
 
863
            if (CSET_DOUBLE(*cb)) {
 
864
                col /= 2;
 
865
                maxcol /= 2;
 
866
            }
 
867
            cs = cb[col];
 
868
        });
 
869
 
 
870
        flags = attrs[col];
 
871
#if OPT_WIDE_CHARS
 
872
        if (widec)
 
873
            wideness = iswide(chars[col] | (widec[col] << 8));
 
874
        else
 
875
            wideness = 0;
 
876
#endif
 
877
        if_OPT_EXT_COLORS(screen, {
 
878
            fbf = SCRN_BUF_FGRND(screen, lastind + topline);
 
879
            fbb = SCRN_BUF_BGRND(screen, lastind + topline);
 
880
            fg_bg = ColorOf(col);
 
881
            /* this combines them, then splits them again.  but
 
882
               extract_fg does more, so seems reasonable */
 
883
            fg = extract_fg(fg_bg, flags);
 
884
            bg = extract_bg(fg_bg, flags);
 
885
        });
 
886
        if_OPT_ISO_TRADITIONAL_COLORS(screen, {
 
887
            fb = SCRN_BUF_COLOR(screen, lastind + topline);
 
888
            fg_bg = ColorOf(col);
 
889
            fg = extract_fg(fg_bg, flags);
 
890
            bg = extract_bg(fg_bg, flags);
 
891
        });
 
892
 
 
893
        gc = updatedXtermGC(screen, flags, fg_bg, hilite);
 
894
        gc_changes |= (flags & (FG_COLOR | BG_COLOR));
 
895
 
 
896
        x = CurCursorX(screen, row + topline, col);
 
897
        lastind = col;
 
898
 
 
899
        for (; col <= maxcol; col++) {
 
900
            if ((attrs[col] != flags)
 
901
                || (hilite && (col > hi_col))
 
902
#if OPT_ISO_COLORS
 
903
                || ((flags & FG_COLOR)
 
904
                    && (extract_fg(ColorOf(col), attrs[col]) != fg))
 
905
                || ((flags & BG_COLOR)
 
906
                    && (extract_bg(ColorOf(col), attrs[col]) != bg))
 
907
#endif
 
908
#if OPT_WIDE_CHARS
 
909
                || (widec
 
910
                    && ((iswide(chars[col] | (widec[col] << 8))) != wideness)
 
911
                    && !((chars[col] | (widec[col] << 8)) == HIDDEN_CHAR))
 
912
#endif
 
913
#if OPT_DEC_CHRSET
 
914
                || (cb[col] != cs)
 
915
#endif
 
916
                ) {
 
917
                TRACE(("ScrnRefresh looping drawXtermText %d..%d:%s\n",
 
918
                       lastind, col,
 
919
                       visibleChars(PAIRED_CHARS(&chars[lastind],
 
920
                                                 WIDEC_PTR(lastind)),
 
921
                                    col - lastind)));
 
922
 
 
923
                test = flags;
 
924
                checkVeryBoldColors(test, fg);
 
925
 
 
926
                x = drawXtermText(screen, test, gc, x, y,
 
927
                                  cs,
 
928
                                  PAIRED_CHARS(&chars[lastind], WIDEC_PTR(lastind)),
 
929
                                  col - lastind, 0);
 
930
 
 
931
                if_OPT_WIDE_CHARS(screen, {
 
932
                    int i;
 
933
                    Char *comb1l = BUF_COM1L(screen->visbuf, row + topline);
 
934
                    Char *comb2l = BUF_COM2L(screen->visbuf, row + topline);
 
935
                    Char *comb1h = BUF_COM1H(screen->visbuf, row + topline);
 
936
                    Char *comb2h = BUF_COM2H(screen->visbuf, row + topline);
 
937
                    for (i = lastind; i < col; i++) {
 
938
                        int my_x = CurCursorX(screen, row + topline, i);
 
939
                        int base = chars[i] | (widec[i] << 8);
 
940
                        int comb1 = comb1l[i] | (comb1h[i] << 8);
 
941
                        int comb2 = comb2l[i] | (comb2h[i] << 8);
 
942
 
 
943
                        if (iswide(base))
 
944
                            my_x = CurCursorX(screen, row + topline, i - 1);
 
945
 
 
946
                        if (comb1 != 0) {
 
947
                            drawXtermText(screen, test, gc, my_x, y, cs,
 
948
                                          PAIRED_CHARS(comb1l + i, comb1h + i),
 
949
                                          1, iswide(base));
 
950
                        }
 
951
 
 
952
                        if (comb2 != 0) {
 
953
                            drawXtermText(screen, test, gc, my_x, y, cs,
 
954
                                          PAIRED_CHARS(comb2l + i, comb2h + i),
 
955
                                          1, iswide(base));
 
956
                        }
 
957
                    }
 
958
                });
 
959
 
 
960
                resetXtermGC(screen, flags, hilite);
 
961
 
 
962
                lastind = col;
 
963
 
 
964
                if (hilite && (col > hi_col))
 
965
                    hilite = False;
 
966
 
 
967
                flags = attrs[col];
 
968
                if_OPT_EXT_COLORS(screen, {
 
969
                    fg_bg = ColorOf(col);
 
970
                    fg = extract_fg(fg_bg, flags);
 
971
                    bg = extract_bg(fg_bg, flags);
 
972
                });
 
973
                if_OPT_ISO_TRADITIONAL_COLORS(screen, {
 
974
                    fg_bg = ColorOf(col);
 
975
                    fg = extract_fg(fg_bg, flags);
 
976
                    bg = extract_bg(fg_bg, flags);
 
977
                });
 
978
                if_OPT_DEC_CHRSET({
 
979
                    cs = cb[col];
 
980
                });
 
981
#if OPT_WIDE_CHARS
 
982
                if (widec)
 
983
                    wideness = iswide(chars[col] | (widec[col] << 8));
 
984
#endif
 
985
 
 
986
                gc = updatedXtermGC(screen, flags, fg_bg, hilite);
 
987
                gc_changes |= (flags & (FG_COLOR | BG_COLOR));
 
988
            }
 
989
 
 
990
            if (chars[col] == 0) {
 
991
#if OPT_WIDE_CHARS
 
992
                if (widec == 0 || widec[col] == 0)
 
993
#endif
 
994
                    chars[col] = ' ';
 
995
            }
 
996
        }
 
997
 
 
998
        TRACE(("ScrnRefresh calling drawXtermText %d..%d:%s\n",
 
999
               lastind, col,
 
1000
               visibleChars(PAIRED_CHARS(&chars[lastind], WIDEC_PTR(lastind)),
 
1001
                            col - lastind)));
 
1002
 
 
1003
        test = flags;
 
1004
        checkVeryBoldColors(test, fg);
 
1005
 
 
1006
        drawXtermText(screen, test, gc, x, y,
 
1007
                      cs,
 
1008
                      PAIRED_CHARS(&chars[lastind], WIDEC_PTR(lastind)),
 
1009
                      col - lastind, 0);
 
1010
 
 
1011
        if_OPT_WIDE_CHARS(screen, {
 
1012
            int i;
 
1013
            Char *comb1l = BUF_COM1L(screen->visbuf, row + topline);
 
1014
            Char *comb2l = BUF_COM2L(screen->visbuf, row + topline);
 
1015
            Char *comb1h = BUF_COM1H(screen->visbuf, row + topline);
 
1016
            Char *comb2h = BUF_COM2H(screen->visbuf, row + topline);
 
1017
            for (i = lastind; i < col; i++) {
 
1018
                int my_x = CurCursorX(screen, row + topline, i);
 
1019
                int base = chars[i] | (widec[i] << 8);
 
1020
                int comb1 = comb1l[i] | (comb1h[i] << 8);
 
1021
                int comb2 = comb2l[i] | (comb2h[i] << 8);
 
1022
 
 
1023
                if (iswide(base))
 
1024
                    my_x = CurCursorX(screen, row + topline, i - 1);
 
1025
 
 
1026
                if (comb1 != 0) {
 
1027
                    drawXtermText(screen, test, gc, my_x, y, cs,
 
1028
                                  PAIRED_CHARS(comb1l + i, comb1h + i),
 
1029
                                  1, iswide(base));
 
1030
                }
 
1031
 
 
1032
                if (comb2 != 0) {
 
1033
                    drawXtermText(screen, test, gc, my_x, y, cs,
 
1034
                                  PAIRED_CHARS(comb2l + i, comb2h + i),
 
1035
                                  1, iswide(base));
 
1036
                }
 
1037
            }
 
1038
        });
 
1039
 
 
1040
        resetXtermGC(screen, flags, hilite);
 
1041
    }
 
1042
 
 
1043
    /*
 
1044
     * If we're in color mode, reset the various GC's to the current
 
1045
     * screen foreground and background so that other functions (e.g.,
 
1046
     * ClearRight) will get the correct colors.
 
1047
     */
 
1048
    if_OPT_ISO_COLORS(screen, {
 
1049
        if (gc_changes & FG_COLOR)
 
1050
            SGR_Foreground(term->cur_foreground);
 
1051
        if (gc_changes & BG_COLOR)
 
1052
            SGR_Background(term->cur_background);
 
1053
    });
 
1054
 
 
1055
#if defined(__CYGWIN__) && defined(TIOCSWINSZ)
 
1056
    if (first_time == 1) {
 
1057
        struct winsize ws;
 
1058
 
 
1059
        first_time = 0;
 
1060
        ws.ws_row = nrows;
 
1061
        ws.ws_col = ncols;
 
1062
        ws.ws_xpixel = term->core.width;
 
1063
        ws.ws_ypixel = term->core.height;
 
1064
        ioctl(screen->respond, TIOCSWINSZ, (char *) &ws);
 
1065
    }
 
1066
#endif
 
1067
    recurse--;
 
1068
}
 
1069
 
 
1070
/*
 
1071
 * Sets the rows first though last of the buffer of screen to spaces.
 
1072
 * Requires first <= last; first, last are rows of screen->buf.
 
1073
 */
 
1074
void
 
1075
ClearBufRows(TScreen * screen,
 
1076
             int first,
 
1077
             int last)
 
1078
{
 
1079
    ScrnBuf buf = screen->visbuf;
 
1080
    int len = screen->max_col + 1;
 
1081
    int row;
 
1082
    int flags = TERM_COLOR_FLAGS;
 
1083
 
 
1084
    TRACE(("ClearBufRows %d..%d\n", first, last));
 
1085
    for (row = first; row <= last; row++) {
 
1086
        ScrnClrWrapped(screen, row);
 
1087
        bzero(BUF_CHARS(buf, row), len);
 
1088
        memset(BUF_ATTRS(buf, row), flags, len);
 
1089
        if_OPT_EXT_COLORS(screen, {
 
1090
            memset(BUF_FGRND(buf, row), term->sgr_foreground, len);
 
1091
            memset(BUF_BGRND(buf, row), term->cur_background, len);
 
1092
        });
 
1093
        if_OPT_ISO_TRADITIONAL_COLORS(screen, {
 
1094
            memset(BUF_COLOR(buf, row), xtermColorPair(), len);
 
1095
        });
 
1096
        if_OPT_DEC_CHRSET({
 
1097
            memset(BUF_CSETS(buf, row), 0, len);
 
1098
        });
 
1099
        if_OPT_WIDE_CHARS(screen, {
 
1100
            memset(BUF_WIDEC(buf, row), 0, len);
 
1101
            memset(BUF_COM1L(buf, row), 0, len);
 
1102
            memset(BUF_COM1H(buf, row), 0, len);
 
1103
            memset(BUF_COM2L(buf, row), 0, len);
 
1104
            memset(BUF_COM2H(buf, row), 0, len);
 
1105
        });
 
1106
    }
 
1107
}
 
1108
 
 
1109
/*
 
1110
  Resizes screen:
 
1111
  1. If new window would have fractional characters, sets window size so as to
 
1112
  discard fractional characters and returns -1.
 
1113
  Minimum screen size is 1 X 1.
 
1114
  Note that this causes another ExposeWindow event.
 
1115
  2. Enlarges screen->buf if necessary.  New space is appended to the bottom
 
1116
  and to the right
 
1117
  3. Reduces  screen->buf if necessary.  Old space is removed from the bottom
 
1118
  and from the right
 
1119
  4. Cursor is positioned as closely to its former position as possible
 
1120
  5. Sets screen->max_row and screen->max_col to reflect new size
 
1121
  6. Maintains the inner border (and clears the border on the screen).
 
1122
  7. Clears origin mode and sets scrolling region to be entire screen.
 
1123
  8. Returns 0
 
1124
  */
 
1125
int
 
1126
ScreenResize(TScreen * screen,
 
1127
             int width,
 
1128
             int height,
 
1129
             unsigned *flags)
 
1130
{
 
1131
    int code;
 
1132
    int rows, cols;
 
1133
    int border = 2 * screen->border;
 
1134
    int move_down_by;
 
1135
#if defined(TIOCSSIZE) && (defined(sun) && !defined(SVR4))
 
1136
    struct ttysize ts;
 
1137
#elif defined(TIOCSWINSZ)
 
1138
    struct winsize ws;
 
1139
#endif /* sun vs TIOCSWINSZ */
 
1140
    Window tw = VWindow(screen);
 
1141
 
 
1142
    TRACE(("ScreenResize %dx%d\n", height, width));
 
1143
 
 
1144
    /* clear the right and bottom internal border because of NorthWest
 
1145
       gravity might have left junk on the right and bottom edges */
 
1146
    if (width >= FullWidth(screen)) {
 
1147
        XClearArea(screen->display, tw,
 
1148
                   FullWidth(screen), 0,        /* right edge */
 
1149
                   0, height,   /* from top to bottom */
 
1150
                   False);
 
1151
    }
 
1152
    if (height >= FullHeight(screen)) {
 
1153
        XClearArea(screen->display, tw,
 
1154
                   0, FullHeight(screen),       /* bottom */
 
1155
                   width, 0,    /* all across the bottom */
 
1156
                   False);
 
1157
    }
 
1158
 
 
1159
    /* round so that it is unlikely the screen will change size on  */
 
1160
    /* small mouse movements.                                       */
 
1161
    rows = (height + FontHeight(screen) / 2 - border) /
 
1162
        FontHeight(screen);
 
1163
    cols = (width + FontWidth(screen) / 2 - border - ScrollbarWidth(screen)) /
 
1164
        FontWidth(screen);
 
1165
    if (rows < 1)
 
1166
        rows = 1;
 
1167
    if (cols < 1)
 
1168
        cols = 1;
 
1169
 
 
1170
    /* update buffers if the screen has changed size */
 
1171
    if (screen->max_row != rows - 1 || screen->max_col != cols - 1) {
 
1172
        int savelines = screen->scrollWidget
 
1173
        ? screen->savelines : 0;
 
1174
        int delta_rows = rows - (screen->max_row + 1);
 
1175
 
 
1176
        TRACE(("...ScreenResize chars %dx%d\n", rows, cols));
 
1177
 
 
1178
        if (screen->cursor_state)
 
1179
            HideCursor();
 
1180
        if (screen->alternate
 
1181
            && term->misc.resizeGravity == SouthWestGravity)
 
1182
            /* swap buffer pointers back to make all this hair work */
 
1183
            SwitchBufPtrs(screen);
 
1184
        if (screen->altbuf)
 
1185
            (void) Reallocate(&screen->altbuf,
 
1186
                              &screen->abuf_address,
 
1187
                              rows,
 
1188
                              cols,
 
1189
                              screen->max_row + 1,
 
1190
                              screen->max_col + 1);
 
1191
        move_down_by = Reallocate(&screen->allbuf,
 
1192
                                  &screen->sbuf_address,
 
1193
                                  rows + savelines, cols,
 
1194
                                  screen->max_row + 1 + savelines,
 
1195
                                  screen->max_col + 1);
 
1196
        screen->visbuf = &screen->allbuf[MAX_PTRS * savelines];
 
1197
 
 
1198
        screen->max_row += delta_rows;
 
1199
        screen->max_col = cols - 1;
 
1200
 
 
1201
        if (term->misc.resizeGravity == SouthWestGravity) {
 
1202
            screen->savedlines -= move_down_by;
 
1203
            if (screen->savedlines < 0)
 
1204
                screen->savedlines = 0;
 
1205
            if (screen->savedlines > screen->savelines)
 
1206
                screen->savedlines = screen->savelines;
 
1207
            if (screen->topline < -screen->savedlines)
 
1208
                screen->topline = -screen->savedlines;
 
1209
            screen->cur_row += move_down_by;
 
1210
            screen->cursor_row += move_down_by;
 
1211
            ScrollSelection(screen, move_down_by);
 
1212
 
 
1213
            if (screen->alternate)
 
1214
                SwitchBufPtrs(screen);  /* put the pointers back */
 
1215
        }
 
1216
 
 
1217
        /* adjust scrolling region */
 
1218
        screen->top_marg = 0;
 
1219
        screen->bot_marg = screen->max_row;
 
1220
        *flags &= ~ORIGIN;
 
1221
 
 
1222
        if (screen->cur_row > screen->max_row)
 
1223
            screen->cur_row = screen->max_row;
 
1224
        if (screen->cur_col > screen->max_col)
 
1225
            screen->cur_col = screen->max_col;
 
1226
 
 
1227
        screen->fullVwin.height = height - border;
 
1228
        screen->fullVwin.width = width - border - screen->fullVwin.sb_info.width;
 
1229
 
 
1230
    } else if (FullHeight(screen) == height && FullWidth(screen) == width)
 
1231
        return (0);             /* nothing has changed at all */
 
1232
 
 
1233
    screen->fullVwin.fullheight = height;
 
1234
    screen->fullVwin.fullwidth = width;
 
1235
 
 
1236
    if (screen->scrollWidget)
 
1237
        ResizeScrollBar(screen);
 
1238
 
 
1239
    ResizeSelection(screen, rows, cols);
 
1240
 
 
1241
#ifndef NO_ACTIVE_ICON
 
1242
    if (screen->iconVwin.window) {
 
1243
        XWindowChanges changes;
 
1244
        screen->iconVwin.width =
 
1245
            (screen->max_col + 1) * screen->iconVwin.f_width;
 
1246
 
 
1247
        screen->iconVwin.height =
 
1248
            (screen->max_row + 1) * screen->iconVwin.f_height;
 
1249
 
 
1250
        changes.width = screen->iconVwin.fullwidth =
 
1251
            screen->iconVwin.width + 2 * screen->border;
 
1252
 
 
1253
        changes.height = screen->iconVwin.fullheight =
 
1254
            screen->iconVwin.height + 2 * screen->border;
 
1255
 
 
1256
        XConfigureWindow(XtDisplay(term), screen->iconVwin.window,
 
1257
                         CWWidth | CWHeight, &changes);
 
1258
    }
 
1259
#endif /* NO_ACTIVE_ICON */
 
1260
 
 
1261
#if defined(TIOCSSIZE) && (defined(sun) && !defined(SVR4))
 
1262
    /* Set tty's idea of window size */
 
1263
    ts.ts_lines = rows;
 
1264
    ts.ts_cols = cols;
 
1265
    code = ioctl(screen->respond, TIOCSSIZE, &ts);
 
1266
    TRACE(("return %d from TIOCSSIZE %dx%d\n", code, rows, cols));
 
1267
#ifdef SIGWINCH
 
1268
    if (screen->pid > 1) {
 
1269
        int pgrp;
 
1270
 
 
1271
        if (ioctl(screen->respond, TIOCGPGRP, &pgrp) != -1)
 
1272
            kill_process_group(pgrp, SIGWINCH);
 
1273
    }
 
1274
#endif /* SIGWINCH */
 
1275
#elif defined(TIOCSWINSZ)
 
1276
    /* Set tty's idea of window size */
 
1277
    ws.ws_row = rows;
 
1278
    ws.ws_col = cols;
 
1279
    ws.ws_xpixel = width;
 
1280
    ws.ws_ypixel = height;
 
1281
    code = ioctl(screen->respond, TIOCSWINSZ, (char *) &ws);
 
1282
    TRACE(("return %d from TIOCSWINSZ %dx%d\n", code, rows, cols));
 
1283
#ifdef notdef                   /* change to SIGWINCH if this doesn't work for you */
 
1284
    if (screen->pid > 1) {
 
1285
        int pgrp;
 
1286
 
 
1287
        if (ioctl(screen->respond, TIOCGPGRP, &pgrp) != -1)
 
1288
            kill_process_group(pgrp, SIGWINCH);
 
1289
    }
 
1290
#endif /* SIGWINCH */
 
1291
#else
 
1292
    TRACE(("ScreenResize cannot do anything to pty\n"));
 
1293
#endif /* sun vs TIOCSWINSZ */
 
1294
    return (0);
 
1295
}
 
1296
 
 
1297
/*
 
1298
 * Return true if any character cell starting at [row,col], for len-cells is
 
1299
 * nonnull.
 
1300
 */
 
1301
Bool
 
1302
non_blank_line(ScrnBuf sb,
 
1303
               int row,
 
1304
               int col,
 
1305
               int len)
 
1306
{
 
1307
    int i;
 
1308
    Char *ptr = BUF_CHARS(sb, row);
 
1309
 
 
1310
    for (i = col; i < len; i++) {
 
1311
        if (ptr[i])
 
1312
            return True;
 
1313
    }
 
1314
 
 
1315
    if_OPT_WIDE_CHARS((&(term->screen)), {
 
1316
        if ((ptr = BUF_WIDEC(sb, row)) != 0) {
 
1317
            for (i = col; i < len; i++) {
 
1318
                if (ptr[i])
 
1319
                    return True;
 
1320
            }
 
1321
        }
 
1322
    });
 
1323
 
 
1324
    return False;
 
1325
}