~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/xterm/util.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: util.c,v 1.3 2000/08/17 19:55:10 cpqbld Exp $
 
3
 */
 
4
 
 
5
/* $XFree86: xc/programs/xterm/util.c,v 3.73 2002/12/27 21:05:23 dickey Exp $ */
 
6
 
 
7
/*
 
8
 * Copyright 1999-2001,2002 by Thomas E. Dickey
 
9
 *
 
10
 *                         All Rights Reserved
 
11
 *
 
12
 * Permission is hereby granted, free of charge, to any person obtaining a
 
13
 * copy of this software and associated documentation files (the
 
14
 * "Software"), to deal in the Software without restriction, including
 
15
 * without limitation the rights to use, copy, modify, merge, publish,
 
16
 * distribute, sublicense, and/or sell copies of the Software, and to
 
17
 * permit persons to whom the Software is furnished to do so, subject to
 
18
 * the following conditions:
 
19
 *
 
20
 * The above copyright notice and this permission notice shall be included
 
21
 * in all copies or substantial portions of the Software.
 
22
 *
 
23
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
24
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
25
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
26
 * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
 
27
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 
28
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 
29
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
30
 *
 
31
 * Except as contained in this notice, the name(s) of the above copyright
 
32
 * holders shall not be used in advertising or otherwise to promote the
 
33
 * sale, use or other dealings in this Software without prior written
 
34
 * authorization.
 
35
 *
 
36
 *
 
37
 * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 
38
 *
 
39
 *                         All Rights Reserved
 
40
 *
 
41
 * Permission to use, copy, modify, and distribute this software and its
 
42
 * documentation for any purpose and without fee is hereby granted,
 
43
 * provided that the above copyright notice appear in all copies and that
 
44
 * both that copyright notice and this permission notice appear in
 
45
 * supporting documentation, and that the name of Digital Equipment
 
46
 * Corporation not be used in advertising or publicity pertaining to
 
47
 * distribution of the software without specific, written prior permission.
 
48
 *
 
49
 *
 
50
 * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 
51
 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 
52
 * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 
53
 * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 
54
 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 
55
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 
56
 * SOFTWARE.
 
57
 */
 
58
 
 
59
/* util.c */
 
60
 
 
61
#include <xterm.h>
 
62
 
 
63
#include <data.h>
 
64
#include <error.h>
 
65
#include <menu.h>
 
66
#include <fontutils.h>
 
67
 
 
68
#if OPT_WIDE_CHARS
 
69
#include <wcwidth.h>
 
70
#endif
 
71
 
 
72
#include <stdio.h>
 
73
#include <ctype.h>
 
74
 
 
75
static int ClearInLine(TScreen * screen, int row, int col, int len);
 
76
static int handle_translated_exposure(TScreen * screen,
 
77
                                      int rect_x,
 
78
                                      int rect_y,
 
79
                                      unsigned rect_width,
 
80
                                      unsigned rect_height);
 
81
static void ClearLeft(TScreen * screen);
 
82
static void CopyWait(TScreen * screen);
 
83
static void horizontal_copy_area(TScreen * screen,
 
84
                                 int firstchar,
 
85
                                 int nchars,
 
86
                                 int amount);
 
87
static void vertical_copy_area(TScreen * screen,
 
88
                               int firstline,
 
89
                               int nlines,
 
90
                               int amount);
 
91
 
 
92
/*
 
93
 * These routines are used for the jump scroll feature
 
94
 */
 
95
void
 
96
FlushScroll(TScreen * screen)
 
97
{
 
98
    int i;
 
99
    int shift = -screen->topline;
 
100
    int bot = screen->max_row - shift;
 
101
    int refreshtop;
 
102
    int refreshheight;
 
103
    int scrolltop;
 
104
    int scrollheight;
 
105
 
 
106
    if (screen->cursor_state)
 
107
        HideCursor();
 
108
    if (screen->scroll_amt > 0) {
 
109
        refreshheight = screen->refresh_amt;
 
110
        scrollheight = screen->bot_marg - screen->top_marg -
 
111
            refreshheight + 1;
 
112
        if ((refreshtop = screen->bot_marg - refreshheight + 1 + shift) >
 
113
            (i = screen->max_row - screen->scroll_amt + 1))
 
114
            refreshtop = i;
 
115
        if (screen->scrollWidget && !screen->alternate
 
116
            && screen->top_marg == 0) {
 
117
            scrolltop = 0;
 
118
            if ((scrollheight += shift) > i)
 
119
                scrollheight = i;
 
120
            if ((i = screen->bot_marg - bot) > 0 &&
 
121
                (refreshheight -= i) < screen->scroll_amt)
 
122
                refreshheight = screen->scroll_amt;
 
123
            if ((i = screen->savedlines) < screen->savelines) {
 
124
                if ((i += screen->scroll_amt) >
 
125
                    screen->savelines)
 
126
                    i = screen->savelines;
 
127
                screen->savedlines = i;
 
128
                ScrollBarDrawThumb(screen->scrollWidget);
 
129
            }
 
130
        } else {
 
131
            scrolltop = screen->top_marg + shift;
 
132
            if ((i = bot - (screen->bot_marg - screen->refresh_amt +
 
133
                            screen->scroll_amt)) > 0) {
 
134
                if (bot < screen->bot_marg)
 
135
                    refreshheight = screen->scroll_amt + i;
 
136
            } else {
 
137
                scrollheight += i;
 
138
                refreshheight = screen->scroll_amt;
 
139
                if ((i = screen->top_marg + screen->scroll_amt -
 
140
                     1 - bot) > 0) {
 
141
                    refreshtop += i;
 
142
                    refreshheight -= i;
 
143
                }
 
144
            }
 
145
        }
 
146
    } else {
 
147
        refreshheight = -screen->refresh_amt;
 
148
        scrollheight = screen->bot_marg - screen->top_marg -
 
149
            refreshheight + 1;
 
150
        refreshtop = screen->top_marg + shift;
 
151
        scrolltop = refreshtop + refreshheight;
 
152
        if ((i = screen->bot_marg - bot) > 0)
 
153
            scrollheight -= i;
 
154
        if ((i = screen->top_marg + refreshheight - 1 - bot) > 0)
 
155
            refreshheight -= i;
 
156
    }
 
157
    scrolling_copy_area(screen, scrolltop + screen->scroll_amt,
 
158
                        scrollheight, screen->scroll_amt);
 
159
    ScrollSelection(screen, -(screen->scroll_amt));
 
160
    screen->scroll_amt = 0;
 
161
    screen->refresh_amt = 0;
 
162
    if (refreshheight > 0) {
 
163
        ClearCurBackground(screen,
 
164
                           (int) refreshtop * FontHeight(screen) + screen->border,
 
165
                           (int) OriginX(screen),
 
166
                           (unsigned) refreshheight * FontHeight(screen),
 
167
                           (unsigned) Width(screen));
 
168
        ScrnRefresh(screen, refreshtop, 0, refreshheight,
 
169
                    screen->max_col + 1, False);
 
170
    }
 
171
}
 
172
 
 
173
int
 
174
AddToRefresh(TScreen * screen)
 
175
{
 
176
    int amount = screen->refresh_amt;
 
177
    int row = screen->cur_row;
 
178
 
 
179
    if (amount == 0)
 
180
        return (0);
 
181
    if (amount > 0) {
 
182
        int bottom;
 
183
 
 
184
        if (row == (bottom = screen->bot_marg) - amount) {
 
185
            screen->refresh_amt++;
 
186
            return (1);
 
187
        }
 
188
        return (row >= bottom - amount + 1 && row <= bottom);
 
189
    } else {
 
190
        int top;
 
191
 
 
192
        amount = -amount;
 
193
        if (row == (top = screen->top_marg) + amount) {
 
194
            screen->refresh_amt--;
 
195
            return (1);
 
196
        }
 
197
        return (row <= top + amount - 1 && row >= top);
 
198
    }
 
199
}
 
200
 
 
201
/*
 
202
 * scrolls the screen by amount lines, erases bottom, doesn't alter
 
203
 * cursor position (i.e. cursor moves down amount relative to text).
 
204
 * All done within the scrolling region, of course.
 
205
 * requires: amount > 0
 
206
 */
 
207
void
 
208
xtermScroll(TScreen * screen, int amount)
 
209
{
 
210
    int i = screen->bot_marg - screen->top_marg + 1;
 
211
    int shift;
 
212
    int bot;
 
213
    int refreshtop = 0;
 
214
    int refreshheight;
 
215
    int scrolltop;
 
216
    int scrollheight;
 
217
 
 
218
    if (screen->cursor_state)
 
219
        HideCursor();
 
220
    if (amount > i)
 
221
        amount = i;
 
222
    if (screen->jumpscroll) {
 
223
        if (screen->scroll_amt > 0) {
 
224
            if (screen->refresh_amt + amount > i)
 
225
                FlushScroll(screen);
 
226
            screen->scroll_amt += amount;
 
227
            screen->refresh_amt += amount;
 
228
        } else {
 
229
            if (screen->scroll_amt < 0)
 
230
                FlushScroll(screen);
 
231
            screen->scroll_amt = amount;
 
232
            screen->refresh_amt = amount;
 
233
        }
 
234
        refreshheight = 0;
 
235
    } else {
 
236
        ScrollSelection(screen, -(amount));
 
237
        if (amount == i) {
 
238
            ClearScreen(screen);
 
239
            return;
 
240
        }
 
241
        shift = -screen->topline;
 
242
        bot = screen->max_row - shift;
 
243
        scrollheight = i - amount;
 
244
        refreshheight = amount;
 
245
        if ((refreshtop = screen->bot_marg - refreshheight + 1 + shift) >
 
246
            (i = screen->max_row - refreshheight + 1))
 
247
            refreshtop = i;
 
248
        if (screen->scrollWidget && !screen->alternate
 
249
            && screen->top_marg == 0) {
 
250
            scrolltop = 0;
 
251
            if ((scrollheight += shift) > i)
 
252
                scrollheight = i;
 
253
            if ((i = screen->savedlines) < screen->savelines) {
 
254
                if ((i += amount) > screen->savelines)
 
255
                    i = screen->savelines;
 
256
                screen->savedlines = i;
 
257
                ScrollBarDrawThumb(screen->scrollWidget);
 
258
            }
 
259
        } else {
 
260
            scrolltop = screen->top_marg + shift;
 
261
            if ((i = screen->bot_marg - bot) > 0) {
 
262
                scrollheight -= i;
 
263
                if ((i = screen->top_marg + amount - 1 - bot) >= 0) {
 
264
                    refreshtop += i;
 
265
                    refreshheight -= i;
 
266
                }
 
267
            }
 
268
        }
 
269
 
 
270
        if (screen->multiscroll && amount == 1 &&
 
271
            screen->topline == 0 && screen->top_marg == 0 &&
 
272
            screen->bot_marg == screen->max_row) {
 
273
            if (screen->incopy < 0 && screen->scrolls == 0)
 
274
                CopyWait(screen);
 
275
            screen->scrolls++;
 
276
        }
 
277
        scrolling_copy_area(screen, scrolltop + amount, scrollheight, amount);
 
278
        if (refreshheight > 0) {
 
279
            ClearCurBackground(screen,
 
280
                               (int) refreshtop * FontHeight(screen) + screen->border,
 
281
                               (int) OriginX(screen),
 
282
                               (unsigned) refreshheight * FontHeight(screen),
 
283
                               (unsigned) Width(screen));
 
284
            if (refreshheight > shift)
 
285
                refreshheight = shift;
 
286
        }
 
287
    }
 
288
    if (screen->scrollWidget && !screen->alternate && screen->top_marg == 0)
 
289
        ScrnDeleteLine(screen, screen->allbuf,
 
290
                       screen->bot_marg + screen->savelines, 0,
 
291
                       amount, screen->max_col + 1);
 
292
    else
 
293
        ScrnDeleteLine(screen, screen->visbuf,
 
294
                       screen->bot_marg, screen->top_marg,
 
295
                       amount, screen->max_col + 1);
 
296
    if (refreshheight > 0)
 
297
        ScrnRefresh(screen, refreshtop, 0, refreshheight,
 
298
                    screen->max_col + 1, False);
 
299
}
 
300
 
 
301
/*
 
302
 * Reverse scrolls the screen by amount lines, erases top, doesn't alter
 
303
 * cursor position (i.e. cursor moves up amount relative to text).
 
304
 * All done within the scrolling region, of course.
 
305
 * Requires: amount > 0
 
306
 */
 
307
void
 
308
RevScroll(TScreen * screen, int amount)
 
309
{
 
310
    int i = screen->bot_marg - screen->top_marg + 1;
 
311
    int shift;
 
312
    int bot;
 
313
    int refreshtop;
 
314
    int refreshheight;
 
315
    int scrolltop;
 
316
    int scrollheight;
 
317
 
 
318
    if (screen->cursor_state)
 
319
        HideCursor();
 
320
    if (amount > i)
 
321
        amount = i;
 
322
    if (screen->jumpscroll) {
 
323
        if (screen->scroll_amt < 0) {
 
324
            if (-screen->refresh_amt + amount > i)
 
325
                FlushScroll(screen);
 
326
            screen->scroll_amt -= amount;
 
327
            screen->refresh_amt -= amount;
 
328
        } else {
 
329
            if (screen->scroll_amt > 0)
 
330
                FlushScroll(screen);
 
331
            screen->scroll_amt = -amount;
 
332
            screen->refresh_amt = -amount;
 
333
        }
 
334
    } else {
 
335
        shift = -screen->topline;
 
336
        bot = screen->max_row - shift;
 
337
        refreshheight = amount;
 
338
        scrollheight = screen->bot_marg - screen->top_marg -
 
339
            refreshheight + 1;
 
340
        refreshtop = screen->top_marg + shift;
 
341
        scrolltop = refreshtop + refreshheight;
 
342
        if ((i = screen->bot_marg - bot) > 0)
 
343
            scrollheight -= i;
 
344
        if ((i = screen->top_marg + refreshheight - 1 - bot) > 0)
 
345
            refreshheight -= i;
 
346
 
 
347
        if (screen->multiscroll && amount == 1 &&
 
348
            screen->topline == 0 && screen->top_marg == 0 &&
 
349
            screen->bot_marg == screen->max_row) {
 
350
            if (screen->incopy < 0 && screen->scrolls == 0)
 
351
                CopyWait(screen);
 
352
            screen->scrolls++;
 
353
        }
 
354
        scrolling_copy_area(screen, scrolltop - amount, scrollheight, -amount);
 
355
        if (refreshheight > 0) {
 
356
            ClearCurBackground(screen,
 
357
                               (int) refreshtop * FontHeight(screen) + screen->border,
 
358
                               (int) OriginX(screen),
 
359
                               (unsigned) refreshheight * FontHeight(screen),
 
360
                               (unsigned) Width(screen));
 
361
        }
 
362
    }
 
363
    ScrnInsertLine(screen, screen->visbuf, screen->bot_marg, screen->top_marg,
 
364
                   amount, screen->max_col + 1);
 
365
}
 
366
 
 
367
/*
 
368
 * If cursor not in scrolling region, returns.  Else,
 
369
 * inserts n blank lines at the cursor's position.  Lines above the
 
370
 * bottom margin are lost.
 
371
 */
 
372
void
 
373
InsertLine(TScreen * screen, int n)
 
374
{
 
375
    int i;
 
376
    int shift;
 
377
    int bot;
 
378
    int refreshtop;
 
379
    int refreshheight;
 
380
    int scrolltop;
 
381
    int scrollheight;
 
382
 
 
383
    if (screen->cur_row < screen->top_marg ||
 
384
        screen->cur_row > screen->bot_marg)
 
385
        return;
 
386
    if (screen->cursor_state)
 
387
        HideCursor();
 
388
    screen->do_wrap = 0;
 
389
    if (n > (i = screen->bot_marg - screen->cur_row + 1))
 
390
        n = i;
 
391
    if (screen->jumpscroll) {
 
392
        if (screen->scroll_amt <= 0 &&
 
393
            screen->cur_row <= -screen->refresh_amt) {
 
394
            if (-screen->refresh_amt + n > screen->max_row + 1)
 
395
                FlushScroll(screen);
 
396
            screen->scroll_amt -= n;
 
397
            screen->refresh_amt -= n;
 
398
        } else if (screen->scroll_amt)
 
399
            FlushScroll(screen);
 
400
    }
 
401
    if (!screen->scroll_amt) {
 
402
        shift = -screen->topline;
 
403
        bot = screen->max_row - shift;
 
404
        refreshheight = n;
 
405
        scrollheight = screen->bot_marg - screen->cur_row - refreshheight + 1;
 
406
        refreshtop = screen->cur_row + shift;
 
407
        scrolltop = refreshtop + refreshheight;
 
408
        if ((i = screen->bot_marg - bot) > 0)
 
409
            scrollheight -= i;
 
410
        if ((i = screen->cur_row + refreshheight - 1 - bot) > 0)
 
411
            refreshheight -= i;
 
412
        vertical_copy_area(screen, scrolltop - n, scrollheight, -n);
 
413
        if (refreshheight > 0) {
 
414
            ClearCurBackground(screen,
 
415
                               (int) refreshtop * FontHeight(screen) + screen->border,
 
416
                               (int) OriginX(screen),
 
417
                               (unsigned) refreshheight * FontHeight(screen),
 
418
                               (unsigned) Width(screen));
 
419
        }
 
420
    }
 
421
    ScrnInsertLine(screen, screen->visbuf, screen->bot_marg, screen->cur_row,
 
422
                   n, screen->max_col + 1);
 
423
}
 
424
 
 
425
/*
 
426
 * If cursor not in scrolling region, returns.  Else, deletes n lines
 
427
 * at the cursor's position, lines added at bottom margin are blank.
 
428
 */
 
429
void
 
430
DeleteLine(TScreen * screen, int n)
 
431
{
 
432
    int i;
 
433
    int shift;
 
434
    int bot;
 
435
    int refreshtop;
 
436
    int refreshheight;
 
437
    int scrolltop;
 
438
    int scrollheight;
 
439
 
 
440
    if (screen->cur_row < screen->top_marg ||
 
441
        screen->cur_row > screen->bot_marg)
 
442
        return;
 
443
    if (screen->cursor_state)
 
444
        HideCursor();
 
445
    screen->do_wrap = 0;
 
446
    if (n > (i = screen->bot_marg - screen->cur_row + 1))
 
447
        n = i;
 
448
    if (screen->jumpscroll) {
 
449
        if (screen->scroll_amt >= 0 && screen->cur_row == screen->top_marg) {
 
450
            if (screen->refresh_amt + n > screen->max_row + 1)
 
451
                FlushScroll(screen);
 
452
            screen->scroll_amt += n;
 
453
            screen->refresh_amt += n;
 
454
        } else if (screen->scroll_amt)
 
455
            FlushScroll(screen);
 
456
    }
 
457
    if (!screen->scroll_amt) {
 
458
 
 
459
        shift = -screen->topline;
 
460
        bot = screen->max_row - shift;
 
461
        scrollheight = i - n;
 
462
        refreshheight = n;
 
463
        if ((refreshtop = screen->bot_marg - refreshheight + 1 + shift) >
 
464
            (i = screen->max_row - refreshheight + 1))
 
465
            refreshtop = i;
 
466
        if (screen->scrollWidget && !screen->alternate && screen->cur_row == 0) {
 
467
            scrolltop = 0;
 
468
            if ((scrollheight += shift) > i)
 
469
                scrollheight = i;
 
470
            if ((i = screen->savedlines) < screen->savelines) {
 
471
                if ((i += n) > screen->savelines)
 
472
                    i = screen->savelines;
 
473
                screen->savedlines = i;
 
474
                ScrollBarDrawThumb(screen->scrollWidget);
 
475
            }
 
476
        } else {
 
477
            scrolltop = screen->cur_row + shift;
 
478
            if ((i = screen->bot_marg - bot) > 0) {
 
479
                scrollheight -= i;
 
480
                if ((i = screen->cur_row + n - 1 - bot) >= 0) {
 
481
                    refreshheight -= i;
 
482
                }
 
483
            }
 
484
        }
 
485
        vertical_copy_area(screen, scrolltop + n, scrollheight, n);
 
486
        if (refreshheight > 0) {
 
487
            ClearCurBackground(screen,
 
488
                               (int) refreshtop * FontHeight(screen) + screen->border,
 
489
                               (int) OriginX(screen),
 
490
                               (unsigned) refreshheight * FontHeight(screen),
 
491
                               (unsigned) Width(screen));
 
492
        }
 
493
    }
 
494
    /* adjust screen->buf */
 
495
    if (screen->scrollWidget && !screen->alternate && screen->cur_row == 0)
 
496
        ScrnDeleteLine(screen, screen->allbuf,
 
497
                       screen->bot_marg + screen->savelines, 0,
 
498
                       n, screen->max_col + 1);
 
499
    else
 
500
        ScrnDeleteLine(screen, screen->visbuf,
 
501
                       screen->bot_marg, screen->cur_row,
 
502
                       n, screen->max_col + 1);
 
503
}
 
504
 
 
505
/*
 
506
 * Insert n blanks at the cursor's position, no wraparound
 
507
 */
 
508
void
 
509
InsertChar(TScreen * screen, int n)
 
510
{
 
511
    register int width;
 
512
 
 
513
    if (screen->cursor_state)
 
514
        HideCursor();
 
515
    screen->do_wrap = 0;
 
516
    if (n > (width = screen->max_col + 1 - screen->cur_col))
 
517
        n = width;
 
518
 
 
519
    if (screen->cur_row - screen->topline <= screen->max_row) {
 
520
        if (!AddToRefresh(screen)) {
 
521
            int col = screen->max_col + 1 - n;
 
522
            if (screen->scroll_amt)
 
523
                FlushScroll(screen);
 
524
 
 
525
#if OPT_DEC_CHRSET
 
526
            if (CSET_DOUBLE(SCRN_BUF_CSETS(screen, screen->cur_row)[0])) {
 
527
                col = (screen->max_col + 1) / 2 - n;
 
528
            }
 
529
#endif
 
530
            /*
 
531
             * prevent InsertChar from shifting the end of a line over
 
532
             * if it is being appended to
 
533
             */
 
534
            if (non_blank_line(screen->visbuf, screen->cur_row,
 
535
                               screen->cur_col, screen->max_col + 1))
 
536
                horizontal_copy_area(screen, screen->cur_col,
 
537
                                     col - screen->cur_col,
 
538
                                     n);
 
539
 
 
540
            ClearCurBackground(
 
541
                                  screen,
 
542
                                  CursorY(screen, screen->cur_row),
 
543
                                  CurCursorX(screen, screen->cur_row, screen->cur_col),
 
544
                                  FontHeight(screen),
 
545
                                  n * CurFontWidth(screen, screen->cur_row));
 
546
        }
 
547
    }
 
548
    /* adjust screen->buf */
 
549
    ScrnInsertChar(screen, n);
 
550
}
 
551
 
 
552
/*
 
553
 * Deletes n chars at the cursor's position, no wraparound.
 
554
 */
 
555
void
 
556
DeleteChar(TScreen * screen, int n)
 
557
{
 
558
    int width;
 
559
 
 
560
    if (screen->cursor_state)
 
561
        HideCursor();
 
562
    screen->do_wrap = 0;
 
563
    if (n > (width = screen->max_col + 1 - screen->cur_col))
 
564
        n = width;
 
565
 
 
566
    if (screen->cur_row - screen->topline <= screen->max_row) {
 
567
        if (!AddToRefresh(screen)) {
 
568
            int col = screen->max_col + 1 - n;
 
569
            if (screen->scroll_amt)
 
570
                FlushScroll(screen);
 
571
 
 
572
#if OPT_DEC_CHRSET
 
573
            if (CSET_DOUBLE(SCRN_BUF_CSETS(screen, screen->cur_row)[0])) {
 
574
                col = (screen->max_col + 1) / 2 - n;
 
575
            }
 
576
#endif
 
577
            horizontal_copy_area(screen, screen->cur_col + n,
 
578
                                 col - screen->cur_col,
 
579
                                 -n);
 
580
 
 
581
            ClearCurBackground(
 
582
                                  screen,
 
583
                                  CursorY(screen, screen->cur_row),
 
584
                                  CurCursorX(screen, screen->cur_row, col),
 
585
                                  FontHeight(screen),
 
586
                                  n * CurFontWidth(screen, screen->cur_row));
 
587
        }
 
588
    }
 
589
    /* adjust screen->buf */
 
590
    ScrnDeleteChar(screen, n);
 
591
}
 
592
 
 
593
/*
 
594
 * Clear from cursor position to beginning of display, inclusive.
 
595
 */
 
596
static void
 
597
ClearAbove(TScreen * screen)
 
598
{
 
599
    if (screen->protected_mode != OFF_PROTECT) {
 
600
        int row;
 
601
        for (row = 0; row <= screen->max_row; row++)
 
602
            ClearInLine(screen, row, 0, screen->max_col + 1);
 
603
    } else {
 
604
        int top, height;
 
605
 
 
606
        if (screen->cursor_state)
 
607
            HideCursor();
 
608
        if ((top = -screen->topline) <= screen->max_row) {
 
609
            if (screen->scroll_amt)
 
610
                FlushScroll(screen);
 
611
            if ((height = screen->cur_row + top) > screen->max_row)
 
612
                height = screen->max_row;
 
613
            if ((height -= top) > 0) {
 
614
                ClearCurBackground(screen,
 
615
                                   top * FontHeight(screen) + screen->border,
 
616
                                   OriginX(screen),
 
617
                                   height * FontHeight(screen),
 
618
                                   Width(screen));
 
619
            }
 
620
        }
 
621
        ClearBufRows(screen, 0, screen->cur_row - 1);
 
622
    }
 
623
 
 
624
    if (screen->cur_row - screen->topline <= screen->max_row)
 
625
        ClearLeft(screen);
 
626
}
 
627
 
 
628
/*
 
629
 * Clear from cursor position to end of display, inclusive.
 
630
 */
 
631
static void
 
632
ClearBelow(TScreen * screen)
 
633
{
 
634
    ClearRight(screen, -1);
 
635
 
 
636
    if (screen->protected_mode != OFF_PROTECT) {
 
637
        int row;
 
638
        for (row = screen->cur_row + 1; row <= screen->max_row; row++)
 
639
            ClearInLine(screen, row, 0, screen->max_col + 1);
 
640
    } else {
 
641
        int top;
 
642
 
 
643
        if ((top = screen->cur_row - screen->topline) <= screen->max_row) {
 
644
            if (screen->scroll_amt)
 
645
                FlushScroll(screen);
 
646
            if (++top <= screen->max_row) {
 
647
                ClearCurBackground(screen,
 
648
                                   top * FontHeight(screen) + screen->border,
 
649
                                   OriginX(screen),
 
650
                                   (screen->max_row - top + 1) * FontHeight(screen),
 
651
                                   Width(screen));
 
652
            }
 
653
        }
 
654
        ClearBufRows(screen, screen->cur_row + 1, screen->max_row);
 
655
    }
 
656
}
 
657
 
 
658
/*
 
659
 * Clear the given row, for the given range of columns, returning 1 if no
 
660
 * protected characters were found, 0 otherwise.
 
661
 */
 
662
static int
 
663
ClearInLine(TScreen * screen, int row, int col, int len)
 
664
{
 
665
    int rc = 1;
 
666
    int flags = TERM_COLOR_FLAGS;
 
667
 
 
668
    /*
 
669
     * If we're clearing to the end of the line, we won't count this as
 
670
     * "drawn" characters.  We'll only do cut/paste on "drawn" characters,
 
671
     * so this has the effect of suppressing trailing blanks from a
 
672
     * selection.
 
673
     */
 
674
    if (col + len < screen->max_col + 1) {
 
675
        flags |= CHARDRAWN;
 
676
    } else {
 
677
        len = screen->max_col + 1 - col;
 
678
    }
 
679
 
 
680
    /* If we've marked protected text on the screen, we'll have to
 
681
     * check each time we do an erase.
 
682
     */
 
683
    if (screen->protected_mode != OFF_PROTECT) {
 
684
        int n;
 
685
        Char *attrs = SCRN_BUF_ATTRS(screen, row) + col;
 
686
        int saved_mode = screen->protected_mode;
 
687
        Bool done;
 
688
 
 
689
        /* disable this branch during recursion */
 
690
        screen->protected_mode = OFF_PROTECT;
 
691
 
 
692
        do {
 
693
            done = True;
 
694
            for (n = 0; n < len; n++) {
 
695
                if (attrs[n] & PROTECTED) {
 
696
                    rc = 0;     /* found a protected segment */
 
697
                    if (n != 0)
 
698
                        ClearInLine(screen, row, col, n);
 
699
                    while ((n < len)
 
700
                           && (attrs[n] & PROTECTED))
 
701
                        n++;
 
702
                    done = False;
 
703
                    break;
 
704
                }
 
705
            }
 
706
            /* setup for another segment, past the protected text */
 
707
            if (!done) {
 
708
                attrs += n;
 
709
                col += n;
 
710
                len -= n;
 
711
            }
 
712
        } while (!done);
 
713
 
 
714
        screen->protected_mode = saved_mode;
 
715
        if (len <= 0)
 
716
            return 0;
 
717
    }
 
718
    /* fall through to the final non-protected segment */
 
719
 
 
720
    if (screen->cursor_state)
 
721
        HideCursor();
 
722
    screen->do_wrap = 0;
 
723
 
 
724
    if (row - screen->topline <= screen->max_row) {
 
725
        if (!AddToRefresh(screen)) {
 
726
            if (screen->scroll_amt)
 
727
                FlushScroll(screen);
 
728
            ClearCurBackground(
 
729
                                  screen,
 
730
                                  CursorY(screen, row),
 
731
                                  CurCursorX(screen, row, col),
 
732
                                  FontHeight(screen),
 
733
                                  len * CurFontWidth(screen, row));
 
734
        }
 
735
    }
 
736
 
 
737
    memset(SCRN_BUF_CHARS(screen, row) + col, ' ', len);
 
738
    memset(SCRN_BUF_ATTRS(screen, row) + col, flags, len);
 
739
 
 
740
    if_OPT_EXT_COLORS(screen, {
 
741
        memset(SCRN_BUF_FGRND(screen, row) + col, term->sgr_foreground, len);
 
742
        memset(SCRN_BUF_BGRND(screen, row) + col, term->cur_background, len);
 
743
    });
 
744
    if_OPT_ISO_TRADITIONAL_COLORS(screen, {
 
745
        memset(SCRN_BUF_COLOR(screen, row) + col, xtermColorPair(), len);
 
746
    });
 
747
    if_OPT_DEC_CHRSET({
 
748
        memset(SCRN_BUF_CSETS(screen, row) + col,
 
749
               curXtermChrSet(screen->cur_row), len);
 
750
    });
 
751
    if_OPT_WIDE_CHARS(screen, {
 
752
        memset(SCRN_BUF_WIDEC(screen, row) + col, 0, len);
 
753
        memset(SCRN_BUF_COM1L(screen, row) + col, 0, len);
 
754
        memset(SCRN_BUF_COM1H(screen, row) + col, 0, len);
 
755
        memset(SCRN_BUF_COM2L(screen, row) + col, 0, len);
 
756
        memset(SCRN_BUF_COM2H(screen, row) + col, 0, len);
 
757
    });
 
758
 
 
759
    return rc;
 
760
}
 
761
 
 
762
/*
 
763
 * Clear the next n characters on the cursor's line, including the cursor's
 
764
 * position.
 
765
 */
 
766
void
 
767
ClearRight(TScreen * screen, int n)
 
768
{
 
769
    int len = (screen->max_col - screen->cur_col + 1);
 
770
 
 
771
    if (n < 0)                  /* the remainder of the line */
 
772
        n = screen->max_col + 1;
 
773
    if (n == 0)                 /* default for 'ECH' */
 
774
        n = 1;
 
775
 
 
776
    if (len > n)
 
777
        len = n;
 
778
 
 
779
    (void) ClearInLine(screen, screen->cur_row, screen->cur_col, len);
 
780
 
 
781
    /* with the right part cleared, we can't be wrapping */
 
782
    ScrnClrWrapped(screen, screen->cur_row);
 
783
}
 
784
 
 
785
/*
 
786
 * Clear first part of cursor's line, inclusive.
 
787
 */
 
788
static void
 
789
ClearLeft(TScreen * screen)
 
790
{
 
791
    (void) ClearInLine(screen, screen->cur_row, 0, screen->cur_col + 1);
 
792
}
 
793
 
 
794
/*
 
795
 * Erase the cursor's line.
 
796
 */
 
797
static void
 
798
ClearLine(TScreen * screen)
 
799
{
 
800
    (void) ClearInLine(screen, screen->cur_row, 0, screen->max_col + 1);
 
801
}
 
802
 
 
803
void
 
804
ClearScreen(TScreen * screen)
 
805
{
 
806
    int top;
 
807
 
 
808
    if (screen->cursor_state)
 
809
        HideCursor();
 
810
    screen->do_wrap = 0;
 
811
    if ((top = -screen->topline) <= screen->max_row) {
 
812
        if (screen->scroll_amt)
 
813
            FlushScroll(screen);
 
814
        ClearCurBackground(screen,
 
815
                           top * FontHeight(screen) + screen->border,
 
816
                           OriginX(screen),
 
817
                           (screen->max_row - top + 1) * FontHeight(screen),
 
818
                           Width(screen));
 
819
    }
 
820
    ClearBufRows(screen, 0, screen->max_row);
 
821
}
 
822
 
 
823
/*
 
824
 * If we've written protected text DEC-style, and are issuing a non-DEC
 
825
 * erase, temporarily reset the protected_mode flag so that the erase will
 
826
 * ignore the protected flags.
 
827
 */
 
828
void
 
829
do_erase_line(TScreen * screen, int param, int mode)
 
830
{
 
831
    int saved_mode = screen->protected_mode;
 
832
 
 
833
    if (saved_mode == DEC_PROTECT
 
834
        && saved_mode != mode)
 
835
        screen->protected_mode = OFF_PROTECT;
 
836
 
 
837
    switch (param) {
 
838
    case -1:                    /* DEFAULT */
 
839
    case 0:
 
840
        ClearRight(screen, -1);
 
841
        break;
 
842
    case 1:
 
843
        ClearLeft(screen);
 
844
        break;
 
845
    case 2:
 
846
        ClearLine(screen);
 
847
        break;
 
848
    }
 
849
    screen->protected_mode = saved_mode;
 
850
}
 
851
 
 
852
/*
 
853
 * Just like 'do_erase_line()', except that this intercepts ED controls.  If we
 
854
 * clear the whole screen, we'll get the return-value from ClearInLine, and
 
855
 * find if there were any protected characters left.  If not, reset the
 
856
 * protected mode flag in the screen data (it's slower).
 
857
 */
 
858
void
 
859
do_erase_display(TScreen * screen, int param, int mode)
 
860
{
 
861
    int saved_mode = screen->protected_mode;
 
862
 
 
863
    if (saved_mode == DEC_PROTECT
 
864
        && saved_mode != mode)
 
865
        screen->protected_mode = OFF_PROTECT;
 
866
 
 
867
    switch (param) {
 
868
    case -1:                    /* DEFAULT */
 
869
    case 0:
 
870
        if (screen->cur_row == 0
 
871
            && screen->cur_col == 0) {
 
872
            screen->protected_mode = saved_mode;
 
873
            do_erase_display(screen, 2, mode);
 
874
            saved_mode = screen->protected_mode;
 
875
        } else
 
876
            ClearBelow(screen);
 
877
        break;
 
878
 
 
879
    case 1:
 
880
        if (screen->cur_row == screen->max_row
 
881
            && screen->cur_col == screen->max_col) {
 
882
            screen->protected_mode = saved_mode;
 
883
            do_erase_display(screen, 2, mode);
 
884
            saved_mode = screen->protected_mode;
 
885
        } else
 
886
            ClearAbove(screen);
 
887
        break;
 
888
 
 
889
    case 2:
 
890
        /*
 
891
         * We use 'ClearScreen()' throughout the remainder of the
 
892
         * program for places where we don't care if the characters are
 
893
         * protected or not.  So we modify the logic around this call
 
894
         * on 'ClearScreen()' to handle protected characters.
 
895
         */
 
896
        if (screen->protected_mode != OFF_PROTECT) {
 
897
            int row;
 
898
            int rc = 1;
 
899
            for (row = 0; row <= screen->max_row; row++)
 
900
                rc &= ClearInLine(screen, row, 0, screen->max_col + 1);
 
901
            if (rc != 0)
 
902
                saved_mode = OFF_PROTECT;
 
903
        } else {
 
904
            ClearScreen(screen);
 
905
        }
 
906
        break;
 
907
 
 
908
    case 3:
 
909
        /* xterm addition - erase saved lines. */
 
910
        screen->savedlines = 0;
 
911
        ScrollBarDrawThumb(screen->scrollWidget);
 
912
        break;
 
913
    }
 
914
    screen->protected_mode = saved_mode;
 
915
}
 
916
 
 
917
static void
 
918
CopyWait(TScreen * screen)
 
919
{
 
920
    XEvent reply;
 
921
    XEvent *rep = &reply;
 
922
 
 
923
    while (1) {
 
924
        XWindowEvent(screen->display, VWindow(screen),
 
925
                     ExposureMask, &reply);
 
926
        switch (reply.type) {
 
927
        case Expose:
 
928
            HandleExposure(screen, &reply);
 
929
            break;
 
930
        case NoExpose:
 
931
        case GraphicsExpose:
 
932
            if (screen->incopy <= 0) {
 
933
                screen->incopy = 1;
 
934
                if (screen->scrolls > 0)
 
935
                    screen->scrolls--;
 
936
            }
 
937
            if (reply.type == GraphicsExpose)
 
938
                HandleExposure(screen, &reply);
 
939
 
 
940
            if ((reply.type == NoExpose) ||
 
941
                ((XExposeEvent *) rep)->count == 0) {
 
942
                if (screen->incopy <= 0 && screen->scrolls > 0)
 
943
                    screen->scrolls--;
 
944
                if (screen->scrolls == 0) {
 
945
                    screen->incopy = 0;
 
946
                    return;
 
947
                }
 
948
                screen->incopy = -1;
 
949
            }
 
950
            break;
 
951
        }
 
952
    }
 
953
}
 
954
 
 
955
/*
 
956
 * used by vertical_copy_area and and horizontal_copy_area
 
957
 */
 
958
static void
 
959
copy_area(TScreen * screen,
 
960
          int src_x,
 
961
          int src_y,
 
962
          unsigned width,
 
963
          unsigned height,
 
964
          int dest_x,
 
965
          int dest_y)
 
966
{
 
967
    /* wait for previous CopyArea to complete unless
 
968
       multiscroll is enabled and active */
 
969
    if (screen->incopy && screen->scrolls == 0)
 
970
        CopyWait(screen);
 
971
    screen->incopy = -1;
 
972
 
 
973
    /* save for translating Expose events */
 
974
    screen->copy_src_x = src_x;
 
975
    screen->copy_src_y = src_y;
 
976
    screen->copy_width = width;
 
977
    screen->copy_height = height;
 
978
    screen->copy_dest_x = dest_x;
 
979
    screen->copy_dest_y = dest_y;
 
980
 
 
981
    XCopyArea(screen->display,
 
982
              VWindow(screen), VWindow(screen),
 
983
              NormalGC(screen),
 
984
              src_x, src_y, width, height, dest_x, dest_y);
 
985
}
 
986
 
 
987
/*
 
988
 * use when inserting or deleting characters on the current line
 
989
 */
 
990
static void
 
991
horizontal_copy_area(TScreen * screen,
 
992
                     int firstchar,     /* char pos on screen to start copying at */
 
993
                     int nchars,
 
994
                     int amount)        /* number of characters to move right */
 
995
{
 
996
    int src_x = CurCursorX(screen, screen->cur_row, firstchar);
 
997
    int src_y = CursorY(screen, screen->cur_row);
 
998
 
 
999
    copy_area(screen, src_x, src_y,
 
1000
              (unsigned) nchars * CurFontWidth(screen, screen->cur_row),
 
1001
              FontHeight(screen),
 
1002
              src_x + amount * CurFontWidth(screen, screen->cur_row), src_y);
 
1003
}
 
1004
 
 
1005
/*
 
1006
 * use when inserting or deleting lines from the screen
 
1007
 */
 
1008
static void
 
1009
vertical_copy_area(TScreen * screen,
 
1010
                   int firstline,       /* line on screen to start copying at */
 
1011
                   int nlines,
 
1012
                   int amount)  /* number of lines to move up (neg=down) */
 
1013
{
 
1014
    if (nlines > 0) {
 
1015
        int src_x = OriginX(screen);
 
1016
        int src_y = firstline * FontHeight(screen) + screen->border;
 
1017
 
 
1018
        copy_area(screen, src_x, src_y,
 
1019
                  (unsigned) Width(screen), nlines * FontHeight(screen),
 
1020
                  src_x, src_y - amount * FontHeight(screen));
 
1021
    }
 
1022
}
 
1023
 
 
1024
/*
 
1025
 * use when scrolling the entire screen
 
1026
 */
 
1027
void
 
1028
scrolling_copy_area(TScreen * screen,
 
1029
                    int firstline,      /* line on screen to start copying at */
 
1030
                    int nlines,
 
1031
                    int amount) /* number of lines to move up (neg=down) */
 
1032
{
 
1033
 
 
1034
    if (nlines > 0) {
 
1035
        vertical_copy_area(screen, firstline, nlines, amount);
 
1036
    }
 
1037
}
 
1038
 
 
1039
/*
 
1040
 * Handler for Expose events on the VT widget.
 
1041
 * Returns 1 iff the area where the cursor was got refreshed.
 
1042
 */
 
1043
int
 
1044
HandleExposure(TScreen * screen, XEvent * event)
 
1045
{
 
1046
    XExposeEvent *reply = (XExposeEvent *) event;
 
1047
 
 
1048
#ifndef NO_ACTIVE_ICON
 
1049
    if (reply->window == screen->iconVwin.window)
 
1050
        screen->whichVwin = &screen->iconVwin;
 
1051
    else
 
1052
        screen->whichVwin = &screen->fullVwin;
 
1053
#endif /* NO_ACTIVE_ICON */
 
1054
 
 
1055
    /* if not doing CopyArea or if this is a GraphicsExpose, don't translate */
 
1056
    if (!screen->incopy || event->type != Expose)
 
1057
        return handle_translated_exposure(screen, reply->x, reply->y,
 
1058
                                          reply->width, reply->height);
 
1059
    else {
 
1060
        /* compute intersection of area being copied with
 
1061
           area being exposed. */
 
1062
        int both_x1 = Max(screen->copy_src_x, reply->x);
 
1063
        int both_y1 = Max(screen->copy_src_y, reply->y);
 
1064
        int both_x2 = Min(screen->copy_src_x + screen->copy_width,
 
1065
                          (unsigned) (reply->x + reply->width));
 
1066
        int both_y2 = Min(screen->copy_src_y + screen->copy_height,
 
1067
                          (unsigned) (reply->y + reply->height));
 
1068
        int value = 0;
 
1069
 
 
1070
        /* was anything copied affected? */
 
1071
        if (both_x2 > both_x1 && both_y2 > both_y1) {
 
1072
            /* do the copied area */
 
1073
            value = handle_translated_exposure
 
1074
                (screen, reply->x + screen->copy_dest_x - screen->copy_src_x,
 
1075
                 reply->y + screen->copy_dest_y - screen->copy_src_y,
 
1076
                 reply->width, reply->height);
 
1077
        }
 
1078
        /* was anything not copied affected? */
 
1079
        if (reply->x < both_x1 || reply->y < both_y1
 
1080
            || reply->x + reply->width > both_x2
 
1081
            || reply->y + reply->height > both_y2)
 
1082
            value = handle_translated_exposure(screen, reply->x, reply->y,
 
1083
                                               reply->width, reply->height);
 
1084
 
 
1085
        return value;
 
1086
    }
 
1087
}
 
1088
 
 
1089
/*
 
1090
 * Called by the ExposeHandler to do the actual repaint after the coordinates
 
1091
 * have been translated to allow for any CopyArea in progress.
 
1092
 * The rectangle passed in is pixel coordinates.
 
1093
 */
 
1094
static int
 
1095
handle_translated_exposure(TScreen * screen,
 
1096
                           int rect_x,
 
1097
                           int rect_y,
 
1098
                           unsigned rect_width,
 
1099
                           unsigned rect_height)
 
1100
{
 
1101
    int toprow, leftcol, nrows, ncols;
 
1102
 
 
1103
    TRACE(("handle_translated_exposure (%d,%d) - (%d,%d)\n",
 
1104
           rect_y, rect_x, rect_height, rect_width));
 
1105
 
 
1106
    toprow = (rect_y - screen->border) / FontHeight(screen);
 
1107
    if (toprow < 0)
 
1108
        toprow = 0;
 
1109
    leftcol = (rect_x - OriginX(screen))
 
1110
        / CurFontWidth(screen, screen->cur_row);
 
1111
    if (leftcol < 0)
 
1112
        leftcol = 0;
 
1113
    nrows = (rect_y + rect_height - 1 - screen->border) /
 
1114
        FontHeight(screen) - toprow + 1;
 
1115
    ncols = (rect_x + rect_width - 1 - OriginX(screen)) /
 
1116
        FontWidth(screen) - leftcol + 1;
 
1117
    toprow -= screen->scrolls;
 
1118
    if (toprow < 0) {
 
1119
        nrows += toprow;
 
1120
        toprow = 0;
 
1121
    }
 
1122
    if (toprow + nrows - 1 > screen->max_row)
 
1123
        nrows = screen->max_row - toprow + 1;
 
1124
    if (leftcol + ncols - 1 > screen->max_col)
 
1125
        ncols = screen->max_col - leftcol + 1;
 
1126
 
 
1127
    if (nrows > 0 && ncols > 0) {
 
1128
        ScrnRefresh(screen, toprow, leftcol, nrows, ncols, False);
 
1129
        if (waiting_for_initial_map) {
 
1130
            first_map_occurred();
 
1131
        }
 
1132
        if (screen->cur_row >= toprow &&
 
1133
            screen->cur_row < toprow + nrows &&
 
1134
            screen->cur_col >= leftcol &&
 
1135
            screen->cur_col < leftcol + ncols)
 
1136
            return (1);
 
1137
 
 
1138
    }
 
1139
    return (0);
 
1140
}
 
1141
 
 
1142
/***====================================================================***/
 
1143
 
 
1144
void
 
1145
GetColors(XtermWidget tw, ScrnColors * pColors)
 
1146
{
 
1147
    TScreen *screen = &tw->screen;
 
1148
 
 
1149
    pColors->which = 0;
 
1150
    SET_COLOR_VALUE(pColors, TEXT_FG, screen->foreground);
 
1151
    SET_COLOR_VALUE(pColors, TEXT_BG, tw->core.background_pixel);
 
1152
    SET_COLOR_VALUE(pColors, TEXT_CURSOR, screen->cursorcolor);
 
1153
    SET_COLOR_VALUE(pColors, MOUSE_FG, screen->mousecolor);
 
1154
    SET_COLOR_VALUE(pColors, MOUSE_BG, screen->mousecolorback);
 
1155
#if OPT_HIGHLIGHT_COLOR
 
1156
    SET_COLOR_VALUE(pColors, HIGHLIGHT_BG, screen->highlightcolor);
 
1157
#endif
 
1158
#if OPT_TEK4014
 
1159
    SET_COLOR_VALUE(pColors, TEK_FG, screen->Tforeground);
 
1160
    SET_COLOR_VALUE(pColors, TEK_BG, screen->Tbackground);
 
1161
#endif
 
1162
}
 
1163
 
 
1164
void
 
1165
ChangeColors(XtermWidget tw, ScrnColors * pNew)
 
1166
{
 
1167
    TScreen *screen = &tw->screen;
 
1168
#if OPT_TEK4014
 
1169
    Window tek = TWindow(screen);
 
1170
#endif
 
1171
 
 
1172
    if (COLOR_DEFINED(pNew, TEXT_BG)) {
 
1173
        tw->core.background_pixel = COLOR_VALUE(pNew, TEXT_BG);
 
1174
    }
 
1175
 
 
1176
    if (COLOR_DEFINED(pNew, TEXT_CURSOR)) {
 
1177
        screen->cursorcolor = COLOR_VALUE(pNew, TEXT_CURSOR);
 
1178
    } else if ((screen->cursorcolor == screen->foreground) &&
 
1179
               (COLOR_DEFINED(pNew, TEXT_FG))) {
 
1180
        screen->cursorcolor = COLOR_VALUE(pNew, TEXT_FG);
 
1181
    }
 
1182
 
 
1183
    if (COLOR_DEFINED(pNew, TEXT_FG)) {
 
1184
        Pixel fg = COLOR_VALUE(pNew, TEXT_FG);
 
1185
        screen->foreground = fg;
 
1186
        XSetForeground(screen->display, NormalGC(screen), fg);
 
1187
        XSetBackground(screen->display, ReverseGC(screen), fg);
 
1188
        XSetForeground(screen->display, NormalBoldGC(screen), fg);
 
1189
        XSetBackground(screen->display, ReverseBoldGC(screen), fg);
 
1190
    }
 
1191
 
 
1192
    if (COLOR_DEFINED(pNew, TEXT_BG)) {
 
1193
        Pixel bg = COLOR_VALUE(pNew, TEXT_BG);
 
1194
        tw->core.background_pixel = bg;
 
1195
        XSetBackground(screen->display, NormalGC(screen), bg);
 
1196
        XSetForeground(screen->display, ReverseGC(screen), bg);
 
1197
        XSetBackground(screen->display, NormalBoldGC(screen), bg);
 
1198
        XSetForeground(screen->display, ReverseBoldGC(screen), bg);
 
1199
        XSetWindowBackground(screen->display, VWindow(screen),
 
1200
                             tw->core.background_pixel);
 
1201
    }
 
1202
 
 
1203
    if (COLOR_DEFINED(pNew, MOUSE_FG) || (COLOR_DEFINED(pNew, MOUSE_BG))) {
 
1204
        if (COLOR_DEFINED(pNew, MOUSE_FG))
 
1205
            screen->mousecolor = COLOR_VALUE(pNew, MOUSE_FG);
 
1206
        if (COLOR_DEFINED(pNew, MOUSE_BG))
 
1207
            screen->mousecolorback = COLOR_VALUE(pNew, MOUSE_BG);
 
1208
 
 
1209
        recolor_cursor(screen->pointer_cursor,
 
1210
                       screen->mousecolor, screen->mousecolorback);
 
1211
        recolor_cursor(screen->arrow,
 
1212
                       screen->mousecolor, screen->mousecolorback);
 
1213
        XDefineCursor(screen->display, VWindow(screen),
 
1214
                      screen->pointer_cursor);
 
1215
 
 
1216
#if OPT_HIGHLIGHT_COLOR
 
1217
        if (COLOR_DEFINED(pNew, HIGHLIGHT_BG)) {
 
1218
            screen->highlightcolor = COLOR_VALUE(pNew, HIGHLIGHT_BG);
 
1219
        }
 
1220
#endif
 
1221
 
 
1222
#if OPT_TEK4014
 
1223
        if (tek)
 
1224
            XDefineCursor(screen->display, tek, screen->arrow);
 
1225
#endif
 
1226
    }
 
1227
#if OPT_TEK4014
 
1228
    if ((tek) && (COLOR_DEFINED(pNew, TEK_FG) || COLOR_DEFINED(pNew, TEK_BG))) {
 
1229
        ChangeTekColors(screen, pNew);
 
1230
    }
 
1231
#endif
 
1232
    set_cursor_gcs(screen);
 
1233
    XClearWindow(screen->display, VWindow(screen));
 
1234
    ScrnRefresh(screen, 0, 0, screen->max_row + 1,
 
1235
                screen->max_col + 1, False);
 
1236
#if OPT_TEK4014
 
1237
    if (screen->Tshow) {
 
1238
        XClearWindow(screen->display, tek);
 
1239
        TekExpose((Widget) NULL, (XEvent *) NULL, (Region) NULL);
 
1240
    }
 
1241
#endif
 
1242
}
 
1243
 
 
1244
void
 
1245
ChangeAnsiColors(XtermWidget tw)
 
1246
{
 
1247
    TScreen *screen = &tw->screen;
 
1248
 
 
1249
    XClearWindow(screen->display, VWindow(screen));
 
1250
    ScrnRefresh(screen, 0, 0,
 
1251
                screen->max_row + 1,
 
1252
                screen->max_col + 1, False);
 
1253
}
 
1254
 
 
1255
/***====================================================================***/
 
1256
 
 
1257
void
 
1258
ReverseVideo(XtermWidget termw)
 
1259
{
 
1260
    TScreen *screen = &termw->screen;
 
1261
    GC tmpGC;
 
1262
    Pixel tmp;
 
1263
#if OPT_TEK4014
 
1264
    Window tek = TWindow(screen);
 
1265
#endif
 
1266
 
 
1267
    /*
 
1268
     * Swap SGR foreground and background colors.  By convention, these are
 
1269
     * the colors assigned to "black" (SGR #0) and "white" (SGR #7).  Also,
 
1270
     * SGR #8 and SGR #15 are the bold (or bright) versions of SGR #0 and
 
1271
     * #7, respectively.
 
1272
     *
 
1273
     * We don't swap colors that happen to match the screen's foreground
 
1274
     * and background because that tends to produce bizarre effects.
 
1275
     */
 
1276
    if_OPT_ISO_COLORS(screen, {
 
1277
        ColorRes tmp2;
 
1278
        EXCHANGE(screen->Acolors[0], screen->Acolors[7], tmp2)
 
1279
            EXCHANGE(screen->Acolors[8], screen->Acolors[15], tmp2)
 
1280
    });
 
1281
 
 
1282
    tmp = termw->core.background_pixel;
 
1283
    if (screen->cursorcolor == screen->foreground)
 
1284
        screen->cursorcolor = tmp;
 
1285
    termw->core.background_pixel = screen->foreground;
 
1286
    screen->foreground = tmp;
 
1287
 
 
1288
    EXCHANGE(screen->mousecolor, screen->mousecolorback, tmp)
 
1289
        EXCHANGE(NormalGC(screen), ReverseGC(screen), tmpGC)
 
1290
        EXCHANGE(NormalBoldGC(screen), ReverseBoldGC(screen), tmpGC)
 
1291
#ifndef NO_ACTIVE_ICON
 
1292
        tmpGC = screen->iconVwin.normalGC;
 
1293
    screen->iconVwin.normalGC = screen->iconVwin.reverseGC;
 
1294
    screen->iconVwin.reverseGC = tmpGC;
 
1295
 
 
1296
    tmpGC = screen->iconVwin.normalboldGC;
 
1297
    screen->iconVwin.normalboldGC = screen->iconVwin.reverseboldGC;
 
1298
    screen->iconVwin.reverseboldGC = tmpGC;
 
1299
#endif /* NO_ACTIVE_ICON */
 
1300
 
 
1301
    recolor_cursor(screen->pointer_cursor,
 
1302
                   screen->mousecolor, screen->mousecolorback);
 
1303
    recolor_cursor(screen->arrow,
 
1304
                   screen->mousecolor, screen->mousecolorback);
 
1305
 
 
1306
    termw->misc.re_verse = !termw->misc.re_verse;
 
1307
 
 
1308
    XDefineCursor(screen->display, VWindow(screen), screen->pointer_cursor);
 
1309
#if OPT_TEK4014
 
1310
    if (tek)
 
1311
        XDefineCursor(screen->display, tek, screen->arrow);
 
1312
#endif
 
1313
 
 
1314
    if (screen->scrollWidget)
 
1315
        ScrollBarReverseVideo(screen->scrollWidget);
 
1316
 
 
1317
    XSetWindowBackground(screen->display, VWindow(screen), termw->core.background_pixel);
 
1318
 
 
1319
    /* the shell-window's background will be used in the first repainting
 
1320
     * on resizing
 
1321
     */
 
1322
    XSetWindowBackground(screen->display, VShellWindow, termw->core.background_pixel);
 
1323
 
 
1324
#if OPT_TEK4014
 
1325
    if (tek) {
 
1326
        TekReverseVideo(screen);
 
1327
    }
 
1328
#endif
 
1329
    XClearWindow(screen->display, VWindow(screen));
 
1330
    ScrnRefresh(screen, 0, 0, screen->max_row + 1,
 
1331
                screen->max_col + 1, False);
 
1332
#if OPT_TEK4014
 
1333
    if (screen->Tshow) {
 
1334
        XClearWindow(screen->display, tek);
 
1335
        TekExpose((Widget) NULL, (XEvent *) NULL, (Region) NULL);
 
1336
    }
 
1337
#endif
 
1338
    ReverseOldColors();
 
1339
    update_reversevideo();
 
1340
}
 
1341
 
 
1342
void
 
1343
recolor_cursor(Cursor cursor,   /* X cursor ID to set */
 
1344
               unsigned long fg,        /* pixel indexes to look up */
 
1345
               unsigned long bg)        /* pixel indexes to look up */
 
1346
{
 
1347
    TScreen *screen = &term->screen;
 
1348
    Display *dpy = screen->display;
 
1349
    XColor colordefs[2];        /* 0 is foreground, 1 is background */
 
1350
 
 
1351
    colordefs[0].pixel = fg;
 
1352
    colordefs[1].pixel = bg;
 
1353
    XQueryColors(dpy, DefaultColormap(dpy, DefaultScreen(dpy)),
 
1354
                 colordefs, 2);
 
1355
    XRecolorCursor(dpy, cursor, colordefs, colordefs + 1);
 
1356
    return;
 
1357
}
 
1358
 
 
1359
/*
 
1360
 * Set the fnt_wide/fnt_high values to a known state, based on the currently
 
1361
 * active font.
 
1362
 */
 
1363
#ifndef NO_ACTIVE_ICON
 
1364
#define SAVE_FONT_INFO(screen) xtermSaveFontInfo (screen, IsIcon(screen) ? screen->fnt_icon : screen->fnt_norm)
 
1365
#else
 
1366
#define SAVE_FONT_INFO(screen) xtermSaveFontInfo (screen, screen->fnt_norm)
 
1367
#endif
 
1368
 
 
1369
#ifdef XRENDERFONT
 
1370
static XftColor *
 
1371
getColor(Pixel pixel)
 
1372
{
 
1373
#define CACHE_SIZE  4
 
1374
    static struct {
 
1375
        XftColor color;
 
1376
        int use;
 
1377
    } cache[CACHE_SIZE];
 
1378
    static int use;
 
1379
    int i;
 
1380
    int oldest, oldestuse;
 
1381
    XColor color;
 
1382
 
 
1383
    oldestuse = 0x7fffffff;
 
1384
    oldest = 0;
 
1385
    for (i = 0; i < CACHE_SIZE; i++) {
 
1386
        if (cache[i].use) {
 
1387
            if (cache[i].color.pixel == pixel) {
 
1388
                cache[i].use = ++use;
 
1389
                return &cache[i].color;
 
1390
            }
 
1391
        }
 
1392
        if (cache[i].use < oldestuse) {
 
1393
            oldestuse = cache[i].use;
 
1394
            oldest = i;
 
1395
        }
 
1396
    }
 
1397
    i = oldest;
 
1398
    color.pixel = pixel;
 
1399
    XQueryColor(term->screen.display, term->core.colormap, &color);
 
1400
    cache[i].color.color.red = color.red;
 
1401
    cache[i].color.color.green = color.green;
 
1402
    cache[i].color.color.blue = color.blue;
 
1403
    cache[i].color.color.alpha = 0xffff;
 
1404
    cache[i].color.pixel = pixel;
 
1405
    cache[i].use = ++use;
 
1406
    return &cache[i].color;
 
1407
}
 
1408
#endif
 
1409
 
 
1410
/*
 
1411
 * Draws text with the specified combination of bold/underline
 
1412
 */
 
1413
int
 
1414
drawXtermText(TScreen * screen,
 
1415
              unsigned flags,
 
1416
              GC gc,
 
1417
              int x,
 
1418
              int y,
 
1419
              int chrset,
 
1420
              PAIRED_CHARS(Char * text, Char * text2),
 
1421
              Cardinal len,
 
1422
              int on_wide)
 
1423
{
 
1424
    int real_length = len;
 
1425
    int draw_len;
 
1426
 
 
1427
#ifdef XRENDERFONT
 
1428
    if (screen->renderFont) {
 
1429
        Display *dpy = screen->display;
 
1430
        XftFont *font;
 
1431
        XGCValues values;
 
1432
 
 
1433
        if (!screen->renderDraw) {
 
1434
            int scr;
 
1435
            Drawable draw = VWindow(screen);
 
1436
            Visual *visual;
 
1437
 
 
1438
            scr = DefaultScreen(dpy);
 
1439
            visual = DefaultVisual(dpy, scr);
 
1440
            screen->renderDraw = XftDrawCreate(dpy, draw, visual,
 
1441
                                               DefaultColormap(dpy, scr));
 
1442
        }
 
1443
        if ((flags & (BOLD | BLINK)) && screen->renderFontBold)
 
1444
            font = screen->renderFontBold;
 
1445
        else
 
1446
            font = screen->renderFont;
 
1447
        XGetGCValues(dpy, gc, GCForeground | GCBackground, &values);
 
1448
        XftDrawRect(screen->renderDraw,
 
1449
                    getColor(values.background),
 
1450
                    x, y,
 
1451
                    len * FontWidth(screen), FontHeight(screen));
 
1452
 
 
1453
        y += font->ascent;
 
1454
#if OPT_WIDE_CHARS
 
1455
        if (text2) {
 
1456
            static XftChar16 *sbuf;
 
1457
            static unsigned slen;
 
1458
            unsigned n;
 
1459
 
 
1460
            if (slen < len) {
 
1461
                slen = (len + 1) * 2;
 
1462
                sbuf = (XftChar16 *) XtRealloc((char *) sbuf, slen * sizeof(XftChar16));
 
1463
            }
 
1464
            for (n = 0; n < len; n++)
 
1465
                sbuf[n] = *text++ | (*text2++ << 8);
 
1466
            XftDrawString16(screen->renderDraw,
 
1467
                            getColor(values.foreground),
 
1468
                            font,
 
1469
                            x, y, sbuf, len);
 
1470
        } else
 
1471
#endif
 
1472
        {
 
1473
            XftDrawString8(screen->renderDraw,
 
1474
                           getColor(values.foreground),
 
1475
                           font,
 
1476
                           x, y, (unsigned char *) text, len);
 
1477
        }
 
1478
 
 
1479
        return x + len * FontWidth(screen);
 
1480
    }
 
1481
#endif
 
1482
#if OPT_WIDE_CHARS
 
1483
    /*
 
1484
     * It's simpler to pass in a null pointer for text2 in places where
 
1485
     * we only use codes through 255.  Fix text2 here so we can increment
 
1486
     * it, etc.
 
1487
     */
 
1488
    if (text2 == 0) {
 
1489
        static Char *dbuf;
 
1490
        static unsigned dlen;
 
1491
        if (dlen <= len) {
 
1492
            dlen = (len + 1) * 2;
 
1493
            dbuf = (Char *) XtRealloc((char *) dbuf, dlen);
 
1494
            memset(dbuf, 0, dlen);
 
1495
        }
 
1496
        text2 = dbuf;
 
1497
    }
 
1498
#endif
 
1499
#if OPT_DEC_CHRSET
 
1500
    if (CSET_DOUBLE(chrset)) {
 
1501
        /* We could try drawing double-size characters in the icon, but
 
1502
         * given that the icon font is usually nil or nil2, there
 
1503
         * doesn't seem to be much point.
 
1504
         */
 
1505
        GC gc2 = ((!IsIcon(screen) && screen->font_doublesize)
 
1506
                  ? xterm_DoubleGC(chrset, flags, gc)
 
1507
                  : 0);
 
1508
 
 
1509
        TRACE(("DRAWTEXT%c[%4d,%4d] (%d) %d:%.*s\n",
 
1510
               screen->cursor_state == OFF ? ' ' : '*',
 
1511
               y, x, chrset, len, (int) len, text));
 
1512
 
 
1513
        if (gc2 != 0) {         /* draw actual double-sized characters */
 
1514
            XFontStruct *fs =
 
1515
            screen->double_fonts[xterm_Double_index(chrset, flags)].fs;
 
1516
            XRectangle rect, *rp = &rect;
 
1517
            Cardinal nr = 1;
 
1518
            int adjust;
 
1519
 
 
1520
            SAVE_FONT_INFO(screen);
 
1521
            screen->fnt_wide *= 2;
 
1522
 
 
1523
            rect.x = 0;
 
1524
            rect.y = 0;
 
1525
            rect.width = len * screen->fnt_wide;
 
1526
            rect.height = FontHeight(screen);
 
1527
 
 
1528
            switch (chrset) {
 
1529
            case CSET_DHL_TOP:
 
1530
                rect.y = -(rect.height / 2);
 
1531
                y -= rect.y;
 
1532
                screen->fnt_high *= 2;
 
1533
                break;
 
1534
            case CSET_DHL_BOT:
 
1535
                rect.y = (rect.height / 2);
 
1536
                y -= rect.y;
 
1537
                screen->fnt_high *= 2;
 
1538
                break;
 
1539
            default:
 
1540
                nr = 0;
 
1541
                break;
 
1542
            }
 
1543
 
 
1544
            /*
 
1545
             * Though it is the right "size", a given bold font may
 
1546
             * be shifted up by a pixel or two.  Shift it back into
 
1547
             * the clipping rectangle.
 
1548
             */
 
1549
            if (nr != 0) {
 
1550
                adjust = fs->ascent
 
1551
                    + fs->descent
 
1552
                    - (2 * FontHeight(screen));
 
1553
                rect.y -= adjust;
 
1554
                y += adjust;
 
1555
            }
 
1556
 
 
1557
            if (nr)
 
1558
                XSetClipRectangles(screen->display, gc2,
 
1559
                                   x, y, rp, nr, YXBanded);
 
1560
            else
 
1561
                XSetClipMask(screen->display, gc2, None);
 
1562
 
 
1563
            /*
 
1564
             * If we're trying to use proportional font, or if the
 
1565
             * font server didn't give us what we asked for wrt
 
1566
             * width, position each character independently.
 
1567
             */
 
1568
            if (screen->fnt_prop
 
1569
                || (fs->min_bounds.width != fs->max_bounds.width)
 
1570
                || (fs->min_bounds.width != 2 * FontWidth(screen))) {
 
1571
                while (len--) {
 
1572
                    x = drawXtermText(screen, flags, gc2,
 
1573
                                      x, y, 0,
 
1574
                                      PAIRED_CHARS(text++, text2++),
 
1575
                                      1, on_wide);
 
1576
                    x += FontWidth(screen);
 
1577
                }
 
1578
            } else {
 
1579
                x = drawXtermText(screen, flags, gc2,
 
1580
                                  x, y, 0,
 
1581
                                  PAIRED_CHARS(text, text2),
 
1582
                                  len, on_wide);
 
1583
                x += len * FontWidth(screen);
 
1584
            }
 
1585
 
 
1586
            TRACE(("drewtext [%4d,%4d]\n", y, x));
 
1587
            SAVE_FONT_INFO(screen);
 
1588
 
 
1589
        } else {                /* simulate double-sized characters */
 
1590
#if OPT_WIDE_CHARS
 
1591
            Char *wide = 0;
 
1592
#endif
 
1593
            unsigned need = 2 * len;
 
1594
            Char *temp = (Char *) malloc(need);
 
1595
            int n = 0;
 
1596
            if_OPT_WIDE_CHARS(screen, {
 
1597
                wide = (Char *) malloc(need);
 
1598
            });
 
1599
            while (len--) {
 
1600
                if_OPT_WIDE_CHARS(screen, {
 
1601
                    wide[n] = *text2++;
 
1602
                    wide[n + 1] = 0;
 
1603
                });
 
1604
                temp[n++] = *text++;
 
1605
                temp[n++] = ' ';
 
1606
            }
 
1607
            x = drawXtermText(screen,
 
1608
                              flags,
 
1609
                              gc,
 
1610
                              x, y,
 
1611
                              0,
 
1612
                              PAIRED_CHARS(temp, wide),
 
1613
                              n,
 
1614
                              on_wide);
 
1615
            free(temp);
 
1616
            if_OPT_WIDE_CHARS(screen, {
 
1617
                free(wide);
 
1618
            });
 
1619
        }
 
1620
        return x;
 
1621
    }
 
1622
#endif
 
1623
    /*
 
1624
     * If we're asked to display a proportional font, do this with a fixed
 
1625
     * pitch.  Yes, it's ugly.  But we cannot distinguish the use of xterm
 
1626
     * as a dumb terminal vs its use as in fullscreen programs such as vi.
 
1627
     */
 
1628
    if (screen->fnt_prop) {
 
1629
        int adj, width;
 
1630
        GC fillGC = gc;         /* might be cursorGC */
 
1631
        XFontStruct *fs = (flags & (BOLD | BLINK))
 
1632
        ? screen->fnt_bold
 
1633
        : screen->fnt_norm;
 
1634
        screen->fnt_prop = False;
 
1635
 
 
1636
#define GC_PAIRS(a,b) \
 
1637
        if (gc == a) fillGC = b; \
 
1638
        if (gc == b) fillGC = a
 
1639
 
 
1640
        /*
 
1641
         * Fill the area where we'll write the characters, otherwise
 
1642
         * we'll get gaps between them.  The cursor is a special case,
 
1643
         * because the XFillRectangle call only uses the foreground,
 
1644
         * while we've set the cursor color in the background.  So we
 
1645
         * need a special GC for that.
 
1646
         */
 
1647
        if (gc == screen->cursorGC
 
1648
            || gc == screen->reversecursorGC)
 
1649
            fillGC = screen->fillCursorGC;
 
1650
        GC_PAIRS(NormalGC(screen), ReverseGC(screen));
 
1651
        GC_PAIRS(NormalBoldGC(screen), ReverseBoldGC(screen));
 
1652
 
 
1653
        XFillRectangle(screen->display, VWindow(screen), fillGC,
 
1654
                       x, y, len * FontWidth(screen), FontHeight(screen));
 
1655
 
 
1656
        while (len--) {
 
1657
            width = XTextWidth(fs, (char *) text, 1);
 
1658
            adj = (FontWidth(screen) - width) / 2;
 
1659
            (void) drawXtermText(screen, flags, gc, x + adj, y,
 
1660
                                 chrset,
 
1661
                                 PAIRED_CHARS(text++, text2++), 1, on_wide);
 
1662
            x += FontWidth(screen);
 
1663
        }
 
1664
        screen->fnt_prop = True;
 
1665
        return x;
 
1666
    }
 
1667
 
 
1668
    /* If the font is complete, draw it as-is */
 
1669
    if (screen->fnt_boxes && !screen->force_box_chars) {
 
1670
        TRACE(("drawXtermText%c[%4d,%4d] (%d) %d:%s\n",
 
1671
               screen->cursor_state == OFF ? ' ' : '*',
 
1672
               y, x, chrset, len,
 
1673
               visibleChars(PAIRED_CHARS(text, text2), len)));
 
1674
        y += FontAscent(screen);
 
1675
 
 
1676
#if OPT_WIDE_CHARS
 
1677
        if (screen->wide_chars) {
 
1678
            int ascent_adjust = 0;
 
1679
            static XChar2b *sbuf;
 
1680
            static Cardinal slen;
 
1681
            Cardinal n;
 
1682
            int ch = text[0] | (text2[0] << 8);
 
1683
            int wideness = (on_wide || iswide(ch) != 0)
 
1684
            && (screen->fnt_dwd != NULL);
 
1685
            unsigned char *endtext = text + len;
 
1686
            if (slen < len) {
 
1687
                slen = (len + 1) * 2;
 
1688
                sbuf = (XChar2b *) XtRealloc((char *) sbuf, slen * sizeof(*sbuf));
 
1689
            }
 
1690
            for (n = 0; n < len; n++) {
 
1691
                sbuf[n].byte2 = *text;
 
1692
                sbuf[n].byte1 = *text2;
 
1693
                text++;
 
1694
                text2++;
 
1695
                if (wideness) {
 
1696
                    /* filter out those pesky fake characters. */
 
1697
                    while (text < endtext
 
1698
                           && *text == HIDDEN_HI
 
1699
                           && *text2 == HIDDEN_LO) {
 
1700
                        text++;
 
1701
                        text2++;
 
1702
                        len--;
 
1703
                    }
 
1704
                }
 
1705
            }
 
1706
            /* This is probably wrong. But it works. */
 
1707
            draw_len = len;
 
1708
            if (wideness
 
1709
                && (screen->fnt_dwd->fid || screen->fnt_dwdb->fid)) {
 
1710
                draw_len = real_length = len * 2;
 
1711
                if ((flags & (BOLD | BLINK)) != 0
 
1712
                    && screen->fnt_dwdb->fid) {
 
1713
                    XSetFont(screen->display, gc, screen->fnt_dwdb->fid);
 
1714
                    ascent_adjust = screen->fnt_dwdb->ascent - screen->fnt_norm->ascent;
 
1715
                } else {
 
1716
                    XSetFont(screen->display, gc, screen->fnt_dwd->fid);
 
1717
                    ascent_adjust = screen->fnt_dwd->ascent - screen->fnt_norm->ascent;
 
1718
                }
 
1719
                /* fix ascent */
 
1720
            } else if ((flags & (BOLD | BLINK)) != 0
 
1721
                       && screen->fnt_bold->fid)
 
1722
                XSetFont(screen->display, gc, screen->fnt_bold->fid);
 
1723
            else
 
1724
                XSetFont(screen->display, gc, screen->fnt_norm->fid);
 
1725
 
 
1726
            if (my_wcwidth(ch) == 0)
 
1727
                XDrawString16(screen->display,
 
1728
                              VWindow(screen), gc,
 
1729
                              x, y + ascent_adjust,
 
1730
                              sbuf, n);
 
1731
            else
 
1732
                XDrawImageString16(screen->display,
 
1733
                                   VWindow(screen), gc,
 
1734
                                   x, y + ascent_adjust,
 
1735
                                   sbuf, n);
 
1736
 
 
1737
        } else
 
1738
#endif
 
1739
        {
 
1740
            XDrawImageString(screen->display, VWindow(screen), gc,
 
1741
                             x, y, (char *) text, len);
 
1742
            draw_len = len;
 
1743
            if ((flags & (BOLD | BLINK)) && screen->enbolden) {
 
1744
#if OPT_CLIP_BOLD
 
1745
                /*
 
1746
                 * This special case is a couple of percent slower, but
 
1747
                 * avoids a lot of pixel trash in rxcurses' hanoi.cmd
 
1748
                 * demo (e.g., 10x20 font).
 
1749
                 */
 
1750
                if (screen->fnt_wide > 2) {
 
1751
                    XRectangle clip;
 
1752
                    int clip_x = x;
 
1753
                    int clip_y = y - FontHeight(screen) + FontDescent(screen);
 
1754
                    clip.x = 0;
 
1755
                    clip.y = 0;
 
1756
                    clip.height = FontHeight(screen);
 
1757
                    clip.width = screen->fnt_wide * len;
 
1758
                    XSetClipRectangles(screen->display, gc,
 
1759
                                       clip_x, clip_y,
 
1760
                                       &clip, 1, Unsorted);
 
1761
                }
 
1762
#endif
 
1763
                XDrawString(screen->display, VWindow(screen), gc,
 
1764
                            x + 1, y, (char *) text, len);
 
1765
#if OPT_CLIP_BOLD
 
1766
                XSetClipMask(screen->display, gc, None);
 
1767
#endif
 
1768
            }
 
1769
        }
 
1770
 
 
1771
        if ((flags & UNDERLINE) && screen->underline) {
 
1772
            if (FontDescent(screen) > 1)
 
1773
                y++;
 
1774
            XDrawLine(screen->display, VWindow(screen), gc,
 
1775
                      x, y, x + draw_len * screen->fnt_wide - 1, y);
 
1776
        }
 
1777
#if OPT_BOX_CHARS
 
1778
#define DrawX(col) x + (col * (screen->fnt_wide))
 
1779
#define DrawSegment(first,last) (void)drawXtermText(screen, flags, gc, DrawX(first), y, chrset, PAIRED_CHARS(text+first, text2+first), last-first, on_wide)
 
1780
    } else {                    /* fill in missing box-characters */
 
1781
        XFontStruct *font = ((flags & BOLD)
 
1782
                             ? screen->fnt_bold
 
1783
                             : screen->fnt_norm);
 
1784
        Cardinal last, first = 0;
 
1785
        Boolean save_force = screen->force_box_chars;
 
1786
        screen->fnt_boxes = True;
 
1787
        for (last = 0; last < len; last++) {
 
1788
            unsigned ch = text[last];
 
1789
            Boolean isMissing;
 
1790
#if OPT_WIDE_CHARS
 
1791
            if (text2 != 0)
 
1792
                ch |= (text2[last] << 8);
 
1793
            isMissing = (ch != HIDDEN_CHAR)
 
1794
                && (xtermMissingChar(ch,
 
1795
                                     ((on_wide || iswide(ch)) && screen->fnt_dwd)
 
1796
                                     ? screen->fnt_dwd
 
1797
                                     : font));
 
1798
#else
 
1799
            isMissing = xtermMissingChar(ch, font);
 
1800
#endif
 
1801
            if (isMissing) {
 
1802
                if (last > first) {
 
1803
                    screen->force_box_chars = False;
 
1804
                    DrawSegment(first, last);
 
1805
                    screen->force_box_chars = save_force;
 
1806
                }
 
1807
                xtermDrawBoxChar(screen, ch, flags, gc, DrawX(last), y);
 
1808
                first = last + 1;
 
1809
            }
 
1810
        }
 
1811
        if (last > first) {
 
1812
            screen->force_box_chars = False;
 
1813
            DrawSegment(first, last);
 
1814
        }
 
1815
        screen->fnt_boxes = False;
 
1816
        screen->force_box_chars = save_force;
 
1817
#endif
 
1818
    }
 
1819
 
 
1820
    return x + real_length * FontWidth(screen);
 
1821
}
 
1822
 
 
1823
/*
 
1824
 * Returns a GC, selected according to the font (reverse/bold/normal) that is
 
1825
 * required for the current position (implied).  The GC is updated with the
 
1826
 * current screen foreground and background colors.
 
1827
 */
 
1828
GC
 
1829
updatedXtermGC(TScreen * screen, int flags, int fg_bg, Bool hilite)
 
1830
{
 
1831
    int my_fg = extract_fg(fg_bg, flags);
 
1832
    int my_bg = extract_bg(fg_bg, flags);
 
1833
    Pixel fg_pix = getXtermForeground(flags, my_fg);
 
1834
    Pixel bg_pix = getXtermBackground(flags, my_bg);
 
1835
#if OPT_HIGHLIGHT_COLOR
 
1836
    Pixel hi_pix = screen->highlightcolor;
 
1837
#endif
 
1838
    GC gc;
 
1839
 
 
1840
    checkVeryBoldColors(flags, my_fg);
 
1841
 
 
1842
    if (ReverseOrHilite(screen, flags, hilite)) {
 
1843
        if (flags & (BOLD | BLINK))
 
1844
            gc = ReverseBoldGC(screen);
 
1845
        else
 
1846
            gc = ReverseGC(screen);
 
1847
 
 
1848
#if OPT_HIGHLIGHT_COLOR
 
1849
        if (hi_pix != screen->foreground
 
1850
            && hi_pix != fg_pix
 
1851
            && hi_pix != bg_pix
 
1852
            && hi_pix != term->dft_foreground) {
 
1853
            bg_pix = fg_pix;
 
1854
            fg_pix = hi_pix;
 
1855
        }
 
1856
#endif
 
1857
        XSetForeground(screen->display, gc, bg_pix);
 
1858
        XSetBackground(screen->display, gc, fg_pix);
 
1859
    } else {
 
1860
        if (flags & (BOLD | BLINK))
 
1861
            gc = NormalBoldGC(screen);
 
1862
        else
 
1863
            gc = NormalGC(screen);
 
1864
 
 
1865
        XSetForeground(screen->display, gc, fg_pix);
 
1866
        XSetBackground(screen->display, gc, bg_pix);
 
1867
    }
 
1868
    return gc;
 
1869
}
 
1870
 
 
1871
/*
 
1872
 * Resets the foreground/background of the GC returned by 'updatedXtermGC()'
 
1873
 * to the values that would be set in SGR_Foreground and SGR_Background. This
 
1874
 * duplicates some logic, but only modifies 1/4 as many GC's.
 
1875
 */
 
1876
void
 
1877
resetXtermGC(TScreen * screen, int flags, Bool hilite)
 
1878
{
 
1879
    Pixel fg_pix = getXtermForeground(flags, term->cur_foreground);
 
1880
    Pixel bg_pix = getXtermBackground(flags, term->cur_background);
 
1881
    GC gc;
 
1882
 
 
1883
    checkVeryBoldColors(flags, term->cur_foreground);
 
1884
 
 
1885
    if (ReverseOrHilite(screen, flags, hilite)) {
 
1886
        if (flags & (BOLD | BLINK))
 
1887
            gc = ReverseBoldGC(screen);
 
1888
        else
 
1889
            gc = ReverseGC(screen);
 
1890
 
 
1891
        XSetForeground(screen->display, gc, bg_pix);
 
1892
        XSetBackground(screen->display, gc, fg_pix);
 
1893
 
 
1894
    } else {
 
1895
        if (flags & (BOLD | BLINK))
 
1896
            gc = NormalBoldGC(screen);
 
1897
        else
 
1898
            gc = NormalGC(screen);
 
1899
 
 
1900
        XSetForeground(screen->display, gc, fg_pix);
 
1901
        XSetBackground(screen->display, gc, bg_pix);
 
1902
    }
 
1903
}
 
1904
 
 
1905
#if OPT_ISO_COLORS
 
1906
/*
 
1907
 * Extract the foreground-color index from a one-byte color pair.  If we've got
 
1908
 * BOLD or UNDERLINE color-mode active, those will be used.
 
1909
 */
 
1910
int
 
1911
extract_fg(unsigned color, unsigned flags)
 
1912
{
 
1913
    int fg = (int) ExtractForeground(color);
 
1914
 
 
1915
    if (term->screen.colorAttrMode
 
1916
        || (fg == (int) ExtractBackground(color))) {
 
1917
        if (term->screen.colorULMode && (flags & UNDERLINE))
 
1918
            fg = COLOR_UL;
 
1919
        if (term->screen.colorBDMode && (flags & BOLD))
 
1920
            fg = COLOR_BD;
 
1921
        if (term->screen.colorBLMode && (flags & BLINK))
 
1922
            fg = COLOR_BL;
 
1923
    }
 
1924
    return fg;
 
1925
}
 
1926
 
 
1927
/*
 
1928
 * Extract the background-color index from a one-byte color pair.
 
1929
 * If we've got INVERSE color-mode active, that will be used.
 
1930
 */
 
1931
int
 
1932
extract_bg(unsigned color, unsigned flags)
 
1933
{
 
1934
    int bg = (int) ExtractBackground(color);
 
1935
 
 
1936
    if (term->screen.colorAttrMode
 
1937
        || (bg == (int) ExtractForeground(color))) {
 
1938
        if (term->screen.colorRVMode && (flags & INVERSE))
 
1939
            bg = COLOR_RV;
 
1940
    }
 
1941
    return bg;
 
1942
}
 
1943
 
 
1944
/*
 
1945
 * Combine the current foreground and background into a single 8-bit number.
 
1946
 * Note that we're storing the SGR foreground, since cur_foreground may be set
 
1947
 * to COLOR_UL, COLOR_BD or COLOR_BL, which would make the code larger than 8
 
1948
 * bits.
 
1949
 *
 
1950
 * This assumes that fg/bg are equal when we override with one of the special
 
1951
 * attribute colors.
 
1952
 */
 
1953
unsigned
 
1954
makeColorPair(int fg, int bg)
 
1955
{
 
1956
    unsigned my_bg = (bg >= 0) && (bg < NUM_ANSI_COLORS) ? (unsigned) bg : 0;
 
1957
    unsigned my_fg = (fg >= 0) && (fg < NUM_ANSI_COLORS) ? (unsigned) fg : my_bg;
 
1958
#if OPT_EXT_COLORS
 
1959
    return (my_fg << 8) | my_bg;
 
1960
#else
 
1961
    return (my_fg << 4) | my_bg;
 
1962
#endif
 
1963
}
 
1964
 
 
1965
/*
 
1966
 * Using the "current" SGR background, clear a rectangle.
 
1967
 */
 
1968
void
 
1969
ClearCurBackground(
 
1970
                      TScreen * screen,
 
1971
                      int top,
 
1972
                      int left,
 
1973
                      unsigned height,
 
1974
                      unsigned width)
 
1975
{
 
1976
    XSetWindowBackground(
 
1977
                            screen->display,
 
1978
                            VWindow(screen),
 
1979
                            getXtermBackground(term->flags, term->cur_background));
 
1980
 
 
1981
    XClearArea(screen->display, VWindow(screen),
 
1982
               left, top, width, height, FALSE);
 
1983
 
 
1984
    XSetWindowBackground(
 
1985
                            screen->display,
 
1986
                            VWindow(screen),
 
1987
                            getXtermBackground(term->flags, MAXCOLORS));
 
1988
}
 
1989
#endif /* OPT_ISO_COLORS */
 
1990
 
 
1991
#if OPT_WIDE_CHARS
 
1992
/*
 
1993
 * Returns a single 8/16-bit number for the given cell
 
1994
 */
 
1995
unsigned
 
1996
getXtermCell(TScreen * screen, int row, int col)
 
1997
{
 
1998
    unsigned ch = SCRN_BUF_CHARS(screen, row)[col];
 
1999
    if_OPT_WIDE_CHARS(screen, {
 
2000
        ch |= (SCRN_BUF_WIDEC(screen, row)[col] << 8);
 
2001
    });
 
2002
    return ch;
 
2003
}
 
2004
 
 
2005
unsigned
 
2006
getXtermCellComb1(TScreen * screen, int row, int col)
 
2007
{
 
2008
    unsigned ch = SCRN_BUF_COM1L(screen, row)[col];
 
2009
    ch |= (SCRN_BUF_COM1H(screen, row)[col] << 8);
 
2010
    return ch;
 
2011
}
 
2012
 
 
2013
unsigned
 
2014
getXtermCellComb2(TScreen * screen, int row, int col)
 
2015
{
 
2016
    unsigned ch = SCRN_BUF_COM2L(screen, row)[col];
 
2017
    ch |= (SCRN_BUF_COM2H(screen, row)[col] << 8);
 
2018
    return ch;
 
2019
}
 
2020
 
 
2021
/*
 
2022
 * Sets a single 8/16-bit number for the given cell
 
2023
 */
 
2024
void
 
2025
putXtermCell(TScreen * screen, int row, int col, int ch)
 
2026
{
 
2027
    SCRN_BUF_CHARS(screen, row)[col] = ch;
 
2028
    if_OPT_WIDE_CHARS(screen, {
 
2029
        SCRN_BUF_WIDEC(screen, row)[col] = (ch >> 8);
 
2030
        SCRN_BUF_COM1L(screen, row)[col] = 0;
 
2031
        SCRN_BUF_COM1H(screen, row)[col] = 0;
 
2032
        SCRN_BUF_COM2L(screen, row)[col] = 0;
 
2033
        SCRN_BUF_COM2H(screen, row)[col] = 0;
 
2034
    });
 
2035
}
 
2036
 
 
2037
/*
 
2038
 * Add a combining character for the given cell
 
2039
 */
 
2040
void
 
2041
addXtermCombining(TScreen * screen, int row, int col, unsigned ch)
 
2042
{
 
2043
    if (!SCRN_BUF_COM1L(screen, row)[col]
 
2044
        && !SCRN_BUF_COM1H(screen, row)[col]) {
 
2045
        SCRN_BUF_COM1L(screen, row)[col] = ch & 0xff;
 
2046
        SCRN_BUF_COM1H(screen, row)[col] = ch >> 8;
 
2047
    } else if (!SCRN_BUF_COM2H(screen, row)[col]) {
 
2048
        SCRN_BUF_COM2L(screen, row)[col] = ch & 0xff;
 
2049
        SCRN_BUF_COM2H(screen, row)[col] = ch >> 8;
 
2050
    }
 
2051
}
 
2052
#endif
 
2053
 
 
2054
#ifdef HAVE_CONFIG_H
 
2055
#ifdef USE_MY_MEMMOVE
 
2056
char *
 
2057
my_memmove(char *s1, char *s2, size_t n)
 
2058
{
 
2059
    if (n != 0) {
 
2060
        if ((s1 + n > s2) && (s2 + n > s1)) {
 
2061
            static char *bfr;
 
2062
            static size_t length;
 
2063
            size_t j;
 
2064
            if (length < n) {
 
2065
                length = (n * 3) / 2;
 
2066
                bfr = ((bfr != 0)
 
2067
                       ? realloc(bfr, length)
 
2068
                       : malloc(length));
 
2069
                if (bfr == NULL)
 
2070
                    SysError(ERROR_MMALLOC);
 
2071
            }
 
2072
            for (j = 0; j < n; j++)
 
2073
                bfr[j] = s2[j];
 
2074
            s2 = bfr;
 
2075
        }
 
2076
        while (n-- != 0)
 
2077
            s1[n] = s2[n];
 
2078
    }
 
2079
    return s1;
 
2080
}
 
2081
#endif /* USE_MY_MEMMOVE */
 
2082
 
 
2083
#ifndef HAVE_STRERROR
 
2084
char *
 
2085
my_strerror(int n)
 
2086
{
 
2087
    extern char *sys_errlist[];
 
2088
    extern int sys_nerr;
 
2089
    if (n > 0 && n < sys_nerr)
 
2090
        return sys_errlist[n];
 
2091
    return "?";
 
2092
}
 
2093
#endif
 
2094
#endif
 
2095
 
 
2096
int
 
2097
char2lower(int ch)
 
2098
{
 
2099
    if (isascii(ch) && isupper(ch)) {   /* lowercasify */
 
2100
#ifdef _tolower
 
2101
        ch = _tolower(ch);
 
2102
#else
 
2103
        ch = tolower(ch);
 
2104
#endif
 
2105
    }
 
2106
    return ch;
 
2107
}
 
2108
 
 
2109
void
 
2110
update_keyboard_type(void)
 
2111
{
 
2112
    update_delete_del();
 
2113
    update_old_fkeys();
 
2114
    update_hp_fkeys();
 
2115
    update_sco_fkeys();
 
2116
    update_sun_fkeys();
 
2117
    update_sun_kbd();
 
2118
}
 
2119
 
 
2120
void
 
2121
set_keyboard_type(xtermKeyboardType type, Bool set)
 
2122
{
 
2123
    xtermKeyboardType save = term->keyboard.type;
 
2124
 
 
2125
    if (set) {
 
2126
        term->keyboard.type = type;
 
2127
    } else {
 
2128
        term->keyboard.type = keyboardIsDefault;
 
2129
    }
 
2130
 
 
2131
    if (save != term->keyboard.type) {
 
2132
        update_keyboard_type();
 
2133
    }
 
2134
}
 
2135
 
 
2136
void
 
2137
toggle_keyboard_type(xtermKeyboardType type)
 
2138
{
 
2139
    xtermKeyboardType save = term->keyboard.type;
 
2140
 
 
2141
    if (term->keyboard.type == type) {
 
2142
        term->keyboard.type = keyboardIsDefault;
 
2143
    } else {
 
2144
        term->keyboard.type = type;
 
2145
    }
 
2146
 
 
2147
    if (save != term->keyboard.type) {
 
2148
        update_keyboard_type();
 
2149
    }
 
2150
}
 
2151
 
 
2152
void
 
2153
init_keyboard_type(xtermKeyboardType type, Bool set)
 
2154
{
 
2155
    static Bool wasSet = False;
 
2156
 
 
2157
    if (set) {
 
2158
        if (wasSet) {
 
2159
            fprintf(stderr, "Conflicting keyboard type option (%d/%d)\n",
 
2160
                    term->keyboard.type, type);
 
2161
        }
 
2162
        term->keyboard.type = type;
 
2163
        wasSet = True;
 
2164
    }
 
2165
}