2
* $Xorg: util.c,v 1.3 2000/08/17 19:55:10 cpqbld Exp $
5
/* $XFree86: xc/programs/xterm/util.c,v 3.73 2002/12/27 21:05:23 dickey Exp $ */
8
* Copyright 1999-2001,2002 by Thomas E. Dickey
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:
20
* The above copyright notice and this permission notice shall be included
21
* in all copies or substantial portions of the Software.
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.
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
37
* Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
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.
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
66
#include <fontutils.h>
75
static int ClearInLine(TScreen * screen, int row, int col, int len);
76
static int handle_translated_exposure(TScreen * screen,
80
unsigned rect_height);
81
static void ClearLeft(TScreen * screen);
82
static void CopyWait(TScreen * screen);
83
static void horizontal_copy_area(TScreen * screen,
87
static void vertical_copy_area(TScreen * screen,
93
* These routines are used for the jump scroll feature
96
FlushScroll(TScreen * screen)
99
int shift = -screen->topline;
100
int bot = screen->max_row - shift;
106
if (screen->cursor_state)
108
if (screen->scroll_amt > 0) {
109
refreshheight = screen->refresh_amt;
110
scrollheight = screen->bot_marg - screen->top_marg -
112
if ((refreshtop = screen->bot_marg - refreshheight + 1 + shift) >
113
(i = screen->max_row - screen->scroll_amt + 1))
115
if (screen->scrollWidget && !screen->alternate
116
&& screen->top_marg == 0) {
118
if ((scrollheight += shift) > 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) >
126
i = screen->savelines;
127
screen->savedlines = i;
128
ScrollBarDrawThumb(screen->scrollWidget);
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;
138
refreshheight = screen->scroll_amt;
139
if ((i = screen->top_marg + screen->scroll_amt -
147
refreshheight = -screen->refresh_amt;
148
scrollheight = screen->bot_marg - screen->top_marg -
150
refreshtop = screen->top_marg + shift;
151
scrolltop = refreshtop + refreshheight;
152
if ((i = screen->bot_marg - bot) > 0)
154
if ((i = screen->top_marg + refreshheight - 1 - bot) > 0)
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);
174
AddToRefresh(TScreen * screen)
176
int amount = screen->refresh_amt;
177
int row = screen->cur_row;
184
if (row == (bottom = screen->bot_marg) - amount) {
185
screen->refresh_amt++;
188
return (row >= bottom - amount + 1 && row <= bottom);
193
if (row == (top = screen->top_marg) + amount) {
194
screen->refresh_amt--;
197
return (row <= top + amount - 1 && row >= top);
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
208
xtermScroll(TScreen * screen, int amount)
210
int i = screen->bot_marg - screen->top_marg + 1;
218
if (screen->cursor_state)
222
if (screen->jumpscroll) {
223
if (screen->scroll_amt > 0) {
224
if (screen->refresh_amt + amount > i)
226
screen->scroll_amt += amount;
227
screen->refresh_amt += amount;
229
if (screen->scroll_amt < 0)
231
screen->scroll_amt = amount;
232
screen->refresh_amt = amount;
236
ScrollSelection(screen, -(amount));
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))
248
if (screen->scrollWidget && !screen->alternate
249
&& screen->top_marg == 0) {
251
if ((scrollheight += shift) > 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);
260
scrolltop = screen->top_marg + shift;
261
if ((i = screen->bot_marg - bot) > 0) {
263
if ((i = screen->top_marg + amount - 1 - bot) >= 0) {
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)
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;
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);
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);
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
308
RevScroll(TScreen * screen, int amount)
310
int i = screen->bot_marg - screen->top_marg + 1;
318
if (screen->cursor_state)
322
if (screen->jumpscroll) {
323
if (screen->scroll_amt < 0) {
324
if (-screen->refresh_amt + amount > i)
326
screen->scroll_amt -= amount;
327
screen->refresh_amt -= amount;
329
if (screen->scroll_amt > 0)
331
screen->scroll_amt = -amount;
332
screen->refresh_amt = -amount;
335
shift = -screen->topline;
336
bot = screen->max_row - shift;
337
refreshheight = amount;
338
scrollheight = screen->bot_marg - screen->top_marg -
340
refreshtop = screen->top_marg + shift;
341
scrolltop = refreshtop + refreshheight;
342
if ((i = screen->bot_marg - bot) > 0)
344
if ((i = screen->top_marg + refreshheight - 1 - bot) > 0)
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)
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));
363
ScrnInsertLine(screen, screen->visbuf, screen->bot_marg, screen->top_marg,
364
amount, screen->max_col + 1);
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.
373
InsertLine(TScreen * screen, int n)
383
if (screen->cur_row < screen->top_marg ||
384
screen->cur_row > screen->bot_marg)
386
if (screen->cursor_state)
389
if (n > (i = screen->bot_marg - screen->cur_row + 1))
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)
396
screen->scroll_amt -= n;
397
screen->refresh_amt -= n;
398
} else if (screen->scroll_amt)
401
if (!screen->scroll_amt) {
402
shift = -screen->topline;
403
bot = screen->max_row - shift;
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)
410
if ((i = screen->cur_row + refreshheight - 1 - bot) > 0)
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));
421
ScrnInsertLine(screen, screen->visbuf, screen->bot_marg, screen->cur_row,
422
n, screen->max_col + 1);
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.
430
DeleteLine(TScreen * screen, int n)
440
if (screen->cur_row < screen->top_marg ||
441
screen->cur_row > screen->bot_marg)
443
if (screen->cursor_state)
446
if (n > (i = screen->bot_marg - screen->cur_row + 1))
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)
452
screen->scroll_amt += n;
453
screen->refresh_amt += n;
454
} else if (screen->scroll_amt)
457
if (!screen->scroll_amt) {
459
shift = -screen->topline;
460
bot = screen->max_row - shift;
461
scrollheight = i - n;
463
if ((refreshtop = screen->bot_marg - refreshheight + 1 + shift) >
464
(i = screen->max_row - refreshheight + 1))
466
if (screen->scrollWidget && !screen->alternate && screen->cur_row == 0) {
468
if ((scrollheight += shift) > 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);
477
scrolltop = screen->cur_row + shift;
478
if ((i = screen->bot_marg - bot) > 0) {
480
if ((i = screen->cur_row + n - 1 - bot) >= 0) {
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));
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);
500
ScrnDeleteLine(screen, screen->visbuf,
501
screen->bot_marg, screen->cur_row,
502
n, screen->max_col + 1);
506
* Insert n blanks at the cursor's position, no wraparound
509
InsertChar(TScreen * screen, int n)
513
if (screen->cursor_state)
516
if (n > (width = screen->max_col + 1 - screen->cur_col))
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)
526
if (CSET_DOUBLE(SCRN_BUF_CSETS(screen, screen->cur_row)[0])) {
527
col = (screen->max_col + 1) / 2 - n;
531
* prevent InsertChar from shifting the end of a line over
532
* if it is being appended to
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,
542
CursorY(screen, screen->cur_row),
543
CurCursorX(screen, screen->cur_row, screen->cur_col),
545
n * CurFontWidth(screen, screen->cur_row));
548
/* adjust screen->buf */
549
ScrnInsertChar(screen, n);
553
* Deletes n chars at the cursor's position, no wraparound.
556
DeleteChar(TScreen * screen, int n)
560
if (screen->cursor_state)
563
if (n > (width = screen->max_col + 1 - screen->cur_col))
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)
573
if (CSET_DOUBLE(SCRN_BUF_CSETS(screen, screen->cur_row)[0])) {
574
col = (screen->max_col + 1) / 2 - n;
577
horizontal_copy_area(screen, screen->cur_col + n,
578
col - screen->cur_col,
583
CursorY(screen, screen->cur_row),
584
CurCursorX(screen, screen->cur_row, col),
586
n * CurFontWidth(screen, screen->cur_row));
589
/* adjust screen->buf */
590
ScrnDeleteChar(screen, n);
594
* Clear from cursor position to beginning of display, inclusive.
597
ClearAbove(TScreen * screen)
599
if (screen->protected_mode != OFF_PROTECT) {
601
for (row = 0; row <= screen->max_row; row++)
602
ClearInLine(screen, row, 0, screen->max_col + 1);
606
if (screen->cursor_state)
608
if ((top = -screen->topline) <= screen->max_row) {
609
if (screen->scroll_amt)
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,
617
height * FontHeight(screen),
621
ClearBufRows(screen, 0, screen->cur_row - 1);
624
if (screen->cur_row - screen->topline <= screen->max_row)
629
* Clear from cursor position to end of display, inclusive.
632
ClearBelow(TScreen * screen)
634
ClearRight(screen, -1);
636
if (screen->protected_mode != OFF_PROTECT) {
638
for (row = screen->cur_row + 1; row <= screen->max_row; row++)
639
ClearInLine(screen, row, 0, screen->max_col + 1);
643
if ((top = screen->cur_row - screen->topline) <= screen->max_row) {
644
if (screen->scroll_amt)
646
if (++top <= screen->max_row) {
647
ClearCurBackground(screen,
648
top * FontHeight(screen) + screen->border,
650
(screen->max_row - top + 1) * FontHeight(screen),
654
ClearBufRows(screen, screen->cur_row + 1, screen->max_row);
659
* Clear the given row, for the given range of columns, returning 1 if no
660
* protected characters were found, 0 otherwise.
663
ClearInLine(TScreen * screen, int row, int col, int len)
666
int flags = TERM_COLOR_FLAGS;
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
674
if (col + len < screen->max_col + 1) {
677
len = screen->max_col + 1 - col;
680
/* If we've marked protected text on the screen, we'll have to
681
* check each time we do an erase.
683
if (screen->protected_mode != OFF_PROTECT) {
685
Char *attrs = SCRN_BUF_ATTRS(screen, row) + col;
686
int saved_mode = screen->protected_mode;
689
/* disable this branch during recursion */
690
screen->protected_mode = OFF_PROTECT;
694
for (n = 0; n < len; n++) {
695
if (attrs[n] & PROTECTED) {
696
rc = 0; /* found a protected segment */
698
ClearInLine(screen, row, col, n);
700
&& (attrs[n] & PROTECTED))
706
/* setup for another segment, past the protected text */
714
screen->protected_mode = saved_mode;
718
/* fall through to the final non-protected segment */
720
if (screen->cursor_state)
724
if (row - screen->topline <= screen->max_row) {
725
if (!AddToRefresh(screen)) {
726
if (screen->scroll_amt)
730
CursorY(screen, row),
731
CurCursorX(screen, row, col),
733
len * CurFontWidth(screen, row));
737
memset(SCRN_BUF_CHARS(screen, row) + col, ' ', len);
738
memset(SCRN_BUF_ATTRS(screen, row) + col, flags, len);
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);
744
if_OPT_ISO_TRADITIONAL_COLORS(screen, {
745
memset(SCRN_BUF_COLOR(screen, row) + col, xtermColorPair(), len);
748
memset(SCRN_BUF_CSETS(screen, row) + col,
749
curXtermChrSet(screen->cur_row), len);
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);
763
* Clear the next n characters on the cursor's line, including the cursor's
767
ClearRight(TScreen * screen, int n)
769
int len = (screen->max_col - screen->cur_col + 1);
771
if (n < 0) /* the remainder of the line */
772
n = screen->max_col + 1;
773
if (n == 0) /* default for 'ECH' */
779
(void) ClearInLine(screen, screen->cur_row, screen->cur_col, len);
781
/* with the right part cleared, we can't be wrapping */
782
ScrnClrWrapped(screen, screen->cur_row);
786
* Clear first part of cursor's line, inclusive.
789
ClearLeft(TScreen * screen)
791
(void) ClearInLine(screen, screen->cur_row, 0, screen->cur_col + 1);
795
* Erase the cursor's line.
798
ClearLine(TScreen * screen)
800
(void) ClearInLine(screen, screen->cur_row, 0, screen->max_col + 1);
804
ClearScreen(TScreen * screen)
808
if (screen->cursor_state)
811
if ((top = -screen->topline) <= screen->max_row) {
812
if (screen->scroll_amt)
814
ClearCurBackground(screen,
815
top * FontHeight(screen) + screen->border,
817
(screen->max_row - top + 1) * FontHeight(screen),
820
ClearBufRows(screen, 0, screen->max_row);
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.
829
do_erase_line(TScreen * screen, int param, int mode)
831
int saved_mode = screen->protected_mode;
833
if (saved_mode == DEC_PROTECT
834
&& saved_mode != mode)
835
screen->protected_mode = OFF_PROTECT;
838
case -1: /* DEFAULT */
840
ClearRight(screen, -1);
849
screen->protected_mode = saved_mode;
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).
859
do_erase_display(TScreen * screen, int param, int mode)
861
int saved_mode = screen->protected_mode;
863
if (saved_mode == DEC_PROTECT
864
&& saved_mode != mode)
865
screen->protected_mode = OFF_PROTECT;
868
case -1: /* DEFAULT */
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;
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;
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.
896
if (screen->protected_mode != OFF_PROTECT) {
899
for (row = 0; row <= screen->max_row; row++)
900
rc &= ClearInLine(screen, row, 0, screen->max_col + 1);
902
saved_mode = OFF_PROTECT;
909
/* xterm addition - erase saved lines. */
910
screen->savedlines = 0;
911
ScrollBarDrawThumb(screen->scrollWidget);
914
screen->protected_mode = saved_mode;
918
CopyWait(TScreen * screen)
921
XEvent *rep = &reply;
924
XWindowEvent(screen->display, VWindow(screen),
925
ExposureMask, &reply);
926
switch (reply.type) {
928
HandleExposure(screen, &reply);
932
if (screen->incopy <= 0) {
934
if (screen->scrolls > 0)
937
if (reply.type == GraphicsExpose)
938
HandleExposure(screen, &reply);
940
if ((reply.type == NoExpose) ||
941
((XExposeEvent *) rep)->count == 0) {
942
if (screen->incopy <= 0 && screen->scrolls > 0)
944
if (screen->scrolls == 0) {
956
* used by vertical_copy_area and and horizontal_copy_area
959
copy_area(TScreen * screen,
967
/* wait for previous CopyArea to complete unless
968
multiscroll is enabled and active */
969
if (screen->incopy && screen->scrolls == 0)
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;
981
XCopyArea(screen->display,
982
VWindow(screen), VWindow(screen),
984
src_x, src_y, width, height, dest_x, dest_y);
988
* use when inserting or deleting characters on the current line
991
horizontal_copy_area(TScreen * screen,
992
int firstchar, /* char pos on screen to start copying at */
994
int amount) /* number of characters to move right */
996
int src_x = CurCursorX(screen, screen->cur_row, firstchar);
997
int src_y = CursorY(screen, screen->cur_row);
999
copy_area(screen, src_x, src_y,
1000
(unsigned) nchars * CurFontWidth(screen, screen->cur_row),
1002
src_x + amount * CurFontWidth(screen, screen->cur_row), src_y);
1006
* use when inserting or deleting lines from the screen
1009
vertical_copy_area(TScreen * screen,
1010
int firstline, /* line on screen to start copying at */
1012
int amount) /* number of lines to move up (neg=down) */
1015
int src_x = OriginX(screen);
1016
int src_y = firstline * FontHeight(screen) + screen->border;
1018
copy_area(screen, src_x, src_y,
1019
(unsigned) Width(screen), nlines * FontHeight(screen),
1020
src_x, src_y - amount * FontHeight(screen));
1025
* use when scrolling the entire screen
1028
scrolling_copy_area(TScreen * screen,
1029
int firstline, /* line on screen to start copying at */
1031
int amount) /* number of lines to move up (neg=down) */
1035
vertical_copy_area(screen, firstline, nlines, amount);
1040
* Handler for Expose events on the VT widget.
1041
* Returns 1 iff the area where the cursor was got refreshed.
1044
HandleExposure(TScreen * screen, XEvent * event)
1046
XExposeEvent *reply = (XExposeEvent *) event;
1048
#ifndef NO_ACTIVE_ICON
1049
if (reply->window == screen->iconVwin.window)
1050
screen->whichVwin = &screen->iconVwin;
1052
screen->whichVwin = &screen->fullVwin;
1053
#endif /* NO_ACTIVE_ICON */
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);
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));
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);
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);
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.
1095
handle_translated_exposure(TScreen * screen,
1098
unsigned rect_width,
1099
unsigned rect_height)
1101
int toprow, leftcol, nrows, ncols;
1103
TRACE(("handle_translated_exposure (%d,%d) - (%d,%d)\n",
1104
rect_y, rect_x, rect_height, rect_width));
1106
toprow = (rect_y - screen->border) / FontHeight(screen);
1109
leftcol = (rect_x - OriginX(screen))
1110
/ CurFontWidth(screen, screen->cur_row);
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;
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;
1127
if (nrows > 0 && ncols > 0) {
1128
ScrnRefresh(screen, toprow, leftcol, nrows, ncols, False);
1129
if (waiting_for_initial_map) {
1130
first_map_occurred();
1132
if (screen->cur_row >= toprow &&
1133
screen->cur_row < toprow + nrows &&
1134
screen->cur_col >= leftcol &&
1135
screen->cur_col < leftcol + ncols)
1142
/***====================================================================***/
1145
GetColors(XtermWidget tw, ScrnColors * pColors)
1147
TScreen *screen = &tw->screen;
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);
1159
SET_COLOR_VALUE(pColors, TEK_FG, screen->Tforeground);
1160
SET_COLOR_VALUE(pColors, TEK_BG, screen->Tbackground);
1165
ChangeColors(XtermWidget tw, ScrnColors * pNew)
1167
TScreen *screen = &tw->screen;
1169
Window tek = TWindow(screen);
1172
if (COLOR_DEFINED(pNew, TEXT_BG)) {
1173
tw->core.background_pixel = COLOR_VALUE(pNew, TEXT_BG);
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);
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);
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);
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);
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);
1216
#if OPT_HIGHLIGHT_COLOR
1217
if (COLOR_DEFINED(pNew, HIGHLIGHT_BG)) {
1218
screen->highlightcolor = COLOR_VALUE(pNew, HIGHLIGHT_BG);
1224
XDefineCursor(screen->display, tek, screen->arrow);
1228
if ((tek) && (COLOR_DEFINED(pNew, TEK_FG) || COLOR_DEFINED(pNew, TEK_BG))) {
1229
ChangeTekColors(screen, pNew);
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);
1237
if (screen->Tshow) {
1238
XClearWindow(screen->display, tek);
1239
TekExpose((Widget) NULL, (XEvent *) NULL, (Region) NULL);
1245
ChangeAnsiColors(XtermWidget tw)
1247
TScreen *screen = &tw->screen;
1249
XClearWindow(screen->display, VWindow(screen));
1250
ScrnRefresh(screen, 0, 0,
1251
screen->max_row + 1,
1252
screen->max_col + 1, False);
1255
/***====================================================================***/
1258
ReverseVideo(XtermWidget termw)
1260
TScreen *screen = &termw->screen;
1264
Window tek = TWindow(screen);
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
1273
* We don't swap colors that happen to match the screen's foreground
1274
* and background because that tends to produce bizarre effects.
1276
if_OPT_ISO_COLORS(screen, {
1278
EXCHANGE(screen->Acolors[0], screen->Acolors[7], tmp2)
1279
EXCHANGE(screen->Acolors[8], screen->Acolors[15], tmp2)
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;
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;
1296
tmpGC = screen->iconVwin.normalboldGC;
1297
screen->iconVwin.normalboldGC = screen->iconVwin.reverseboldGC;
1298
screen->iconVwin.reverseboldGC = tmpGC;
1299
#endif /* NO_ACTIVE_ICON */
1301
recolor_cursor(screen->pointer_cursor,
1302
screen->mousecolor, screen->mousecolorback);
1303
recolor_cursor(screen->arrow,
1304
screen->mousecolor, screen->mousecolorback);
1306
termw->misc.re_verse = !termw->misc.re_verse;
1308
XDefineCursor(screen->display, VWindow(screen), screen->pointer_cursor);
1311
XDefineCursor(screen->display, tek, screen->arrow);
1314
if (screen->scrollWidget)
1315
ScrollBarReverseVideo(screen->scrollWidget);
1317
XSetWindowBackground(screen->display, VWindow(screen), termw->core.background_pixel);
1319
/* the shell-window's background will be used in the first repainting
1322
XSetWindowBackground(screen->display, VShellWindow, termw->core.background_pixel);
1326
TekReverseVideo(screen);
1329
XClearWindow(screen->display, VWindow(screen));
1330
ScrnRefresh(screen, 0, 0, screen->max_row + 1,
1331
screen->max_col + 1, False);
1333
if (screen->Tshow) {
1334
XClearWindow(screen->display, tek);
1335
TekExpose((Widget) NULL, (XEvent *) NULL, (Region) NULL);
1339
update_reversevideo();
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 */
1347
TScreen *screen = &term->screen;
1348
Display *dpy = screen->display;
1349
XColor colordefs[2]; /* 0 is foreground, 1 is background */
1351
colordefs[0].pixel = fg;
1352
colordefs[1].pixel = bg;
1353
XQueryColors(dpy, DefaultColormap(dpy, DefaultScreen(dpy)),
1355
XRecolorCursor(dpy, cursor, colordefs, colordefs + 1);
1360
* Set the fnt_wide/fnt_high values to a known state, based on the currently
1363
#ifndef NO_ACTIVE_ICON
1364
#define SAVE_FONT_INFO(screen) xtermSaveFontInfo (screen, IsIcon(screen) ? screen->fnt_icon : screen->fnt_norm)
1366
#define SAVE_FONT_INFO(screen) xtermSaveFontInfo (screen, screen->fnt_norm)
1371
getColor(Pixel pixel)
1373
#define CACHE_SIZE 4
1377
} cache[CACHE_SIZE];
1380
int oldest, oldestuse;
1383
oldestuse = 0x7fffffff;
1385
for (i = 0; i < CACHE_SIZE; i++) {
1387
if (cache[i].color.pixel == pixel) {
1388
cache[i].use = ++use;
1389
return &cache[i].color;
1392
if (cache[i].use < oldestuse) {
1393
oldestuse = cache[i].use;
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;
1411
* Draws text with the specified combination of bold/underline
1414
drawXtermText(TScreen * screen,
1420
PAIRED_CHARS(Char * text, Char * text2),
1424
int real_length = len;
1428
if (screen->renderFont) {
1429
Display *dpy = screen->display;
1433
if (!screen->renderDraw) {
1435
Drawable draw = VWindow(screen);
1438
scr = DefaultScreen(dpy);
1439
visual = DefaultVisual(dpy, scr);
1440
screen->renderDraw = XftDrawCreate(dpy, draw, visual,
1441
DefaultColormap(dpy, scr));
1443
if ((flags & (BOLD | BLINK)) && screen->renderFontBold)
1444
font = screen->renderFontBold;
1446
font = screen->renderFont;
1447
XGetGCValues(dpy, gc, GCForeground | GCBackground, &values);
1448
XftDrawRect(screen->renderDraw,
1449
getColor(values.background),
1451
len * FontWidth(screen), FontHeight(screen));
1456
static XftChar16 *sbuf;
1457
static unsigned slen;
1461
slen = (len + 1) * 2;
1462
sbuf = (XftChar16 *) XtRealloc((char *) sbuf, slen * sizeof(XftChar16));
1464
for (n = 0; n < len; n++)
1465
sbuf[n] = *text++ | (*text2++ << 8);
1466
XftDrawString16(screen->renderDraw,
1467
getColor(values.foreground),
1473
XftDrawString8(screen->renderDraw,
1474
getColor(values.foreground),
1476
x, y, (unsigned char *) text, len);
1479
return x + len * FontWidth(screen);
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
1490
static unsigned dlen;
1492
dlen = (len + 1) * 2;
1493
dbuf = (Char *) XtRealloc((char *) dbuf, dlen);
1494
memset(dbuf, 0, dlen);
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.
1505
GC gc2 = ((!IsIcon(screen) && screen->font_doublesize)
1506
? xterm_DoubleGC(chrset, flags, gc)
1509
TRACE(("DRAWTEXT%c[%4d,%4d] (%d) %d:%.*s\n",
1510
screen->cursor_state == OFF ? ' ' : '*',
1511
y, x, chrset, len, (int) len, text));
1513
if (gc2 != 0) { /* draw actual double-sized characters */
1515
screen->double_fonts[xterm_Double_index(chrset, flags)].fs;
1516
XRectangle rect, *rp = ▭
1520
SAVE_FONT_INFO(screen);
1521
screen->fnt_wide *= 2;
1525
rect.width = len * screen->fnt_wide;
1526
rect.height = FontHeight(screen);
1530
rect.y = -(rect.height / 2);
1532
screen->fnt_high *= 2;
1535
rect.y = (rect.height / 2);
1537
screen->fnt_high *= 2;
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.
1552
- (2 * FontHeight(screen));
1558
XSetClipRectangles(screen->display, gc2,
1559
x, y, rp, nr, YXBanded);
1561
XSetClipMask(screen->display, gc2, None);
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.
1568
if (screen->fnt_prop
1569
|| (fs->min_bounds.width != fs->max_bounds.width)
1570
|| (fs->min_bounds.width != 2 * FontWidth(screen))) {
1572
x = drawXtermText(screen, flags, gc2,
1574
PAIRED_CHARS(text++, text2++),
1576
x += FontWidth(screen);
1579
x = drawXtermText(screen, flags, gc2,
1581
PAIRED_CHARS(text, text2),
1583
x += len * FontWidth(screen);
1586
TRACE(("drewtext [%4d,%4d]\n", y, x));
1587
SAVE_FONT_INFO(screen);
1589
} else { /* simulate double-sized characters */
1593
unsigned need = 2 * len;
1594
Char *temp = (Char *) malloc(need);
1596
if_OPT_WIDE_CHARS(screen, {
1597
wide = (Char *) malloc(need);
1600
if_OPT_WIDE_CHARS(screen, {
1604
temp[n++] = *text++;
1607
x = drawXtermText(screen,
1612
PAIRED_CHARS(temp, wide),
1616
if_OPT_WIDE_CHARS(screen, {
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.
1628
if (screen->fnt_prop) {
1630
GC fillGC = gc; /* might be cursorGC */
1631
XFontStruct *fs = (flags & (BOLD | BLINK))
1634
screen->fnt_prop = False;
1636
#define GC_PAIRS(a,b) \
1637
if (gc == a) fillGC = b; \
1638
if (gc == b) fillGC = a
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.
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));
1653
XFillRectangle(screen->display, VWindow(screen), fillGC,
1654
x, y, len * FontWidth(screen), FontHeight(screen));
1657
width = XTextWidth(fs, (char *) text, 1);
1658
adj = (FontWidth(screen) - width) / 2;
1659
(void) drawXtermText(screen, flags, gc, x + adj, y,
1661
PAIRED_CHARS(text++, text2++), 1, on_wide);
1662
x += FontWidth(screen);
1664
screen->fnt_prop = True;
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 ? ' ' : '*',
1673
visibleChars(PAIRED_CHARS(text, text2), len)));
1674
y += FontAscent(screen);
1677
if (screen->wide_chars) {
1678
int ascent_adjust = 0;
1679
static XChar2b *sbuf;
1680
static Cardinal slen;
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;
1687
slen = (len + 1) * 2;
1688
sbuf = (XChar2b *) XtRealloc((char *) sbuf, slen * sizeof(*sbuf));
1690
for (n = 0; n < len; n++) {
1691
sbuf[n].byte2 = *text;
1692
sbuf[n].byte1 = *text2;
1696
/* filter out those pesky fake characters. */
1697
while (text < endtext
1698
&& *text == HIDDEN_HI
1699
&& *text2 == HIDDEN_LO) {
1706
/* This is probably wrong. But it works. */
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;
1716
XSetFont(screen->display, gc, screen->fnt_dwd->fid);
1717
ascent_adjust = screen->fnt_dwd->ascent - screen->fnt_norm->ascent;
1720
} else if ((flags & (BOLD | BLINK)) != 0
1721
&& screen->fnt_bold->fid)
1722
XSetFont(screen->display, gc, screen->fnt_bold->fid);
1724
XSetFont(screen->display, gc, screen->fnt_norm->fid);
1726
if (my_wcwidth(ch) == 0)
1727
XDrawString16(screen->display,
1728
VWindow(screen), gc,
1729
x, y + ascent_adjust,
1732
XDrawImageString16(screen->display,
1733
VWindow(screen), gc,
1734
x, y + ascent_adjust,
1740
XDrawImageString(screen->display, VWindow(screen), gc,
1741
x, y, (char *) text, len);
1743
if ((flags & (BOLD | BLINK)) && screen->enbolden) {
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).
1750
if (screen->fnt_wide > 2) {
1753
int clip_y = y - FontHeight(screen) + FontDescent(screen);
1756
clip.height = FontHeight(screen);
1757
clip.width = screen->fnt_wide * len;
1758
XSetClipRectangles(screen->display, gc,
1760
&clip, 1, Unsorted);
1763
XDrawString(screen->display, VWindow(screen), gc,
1764
x + 1, y, (char *) text, len);
1766
XSetClipMask(screen->display, gc, None);
1771
if ((flags & UNDERLINE) && screen->underline) {
1772
if (FontDescent(screen) > 1)
1774
XDrawLine(screen->display, VWindow(screen), gc,
1775
x, y, x + draw_len * screen->fnt_wide - 1, y);
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)
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];
1792
ch |= (text2[last] << 8);
1793
isMissing = (ch != HIDDEN_CHAR)
1794
&& (xtermMissingChar(ch,
1795
((on_wide || iswide(ch)) && screen->fnt_dwd)
1799
isMissing = xtermMissingChar(ch, font);
1803
screen->force_box_chars = False;
1804
DrawSegment(first, last);
1805
screen->force_box_chars = save_force;
1807
xtermDrawBoxChar(screen, ch, flags, gc, DrawX(last), y);
1812
screen->force_box_chars = False;
1813
DrawSegment(first, last);
1815
screen->fnt_boxes = False;
1816
screen->force_box_chars = save_force;
1820
return x + real_length * FontWidth(screen);
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.
1829
updatedXtermGC(TScreen * screen, int flags, int fg_bg, Bool hilite)
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;
1840
checkVeryBoldColors(flags, my_fg);
1842
if (ReverseOrHilite(screen, flags, hilite)) {
1843
if (flags & (BOLD | BLINK))
1844
gc = ReverseBoldGC(screen);
1846
gc = ReverseGC(screen);
1848
#if OPT_HIGHLIGHT_COLOR
1849
if (hi_pix != screen->foreground
1852
&& hi_pix != term->dft_foreground) {
1857
XSetForeground(screen->display, gc, bg_pix);
1858
XSetBackground(screen->display, gc, fg_pix);
1860
if (flags & (BOLD | BLINK))
1861
gc = NormalBoldGC(screen);
1863
gc = NormalGC(screen);
1865
XSetForeground(screen->display, gc, fg_pix);
1866
XSetBackground(screen->display, gc, bg_pix);
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.
1877
resetXtermGC(TScreen * screen, int flags, Bool hilite)
1879
Pixel fg_pix = getXtermForeground(flags, term->cur_foreground);
1880
Pixel bg_pix = getXtermBackground(flags, term->cur_background);
1883
checkVeryBoldColors(flags, term->cur_foreground);
1885
if (ReverseOrHilite(screen, flags, hilite)) {
1886
if (flags & (BOLD | BLINK))
1887
gc = ReverseBoldGC(screen);
1889
gc = ReverseGC(screen);
1891
XSetForeground(screen->display, gc, bg_pix);
1892
XSetBackground(screen->display, gc, fg_pix);
1895
if (flags & (BOLD | BLINK))
1896
gc = NormalBoldGC(screen);
1898
gc = NormalGC(screen);
1900
XSetForeground(screen->display, gc, fg_pix);
1901
XSetBackground(screen->display, gc, bg_pix);
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.
1911
extract_fg(unsigned color, unsigned flags)
1913
int fg = (int) ExtractForeground(color);
1915
if (term->screen.colorAttrMode
1916
|| (fg == (int) ExtractBackground(color))) {
1917
if (term->screen.colorULMode && (flags & UNDERLINE))
1919
if (term->screen.colorBDMode && (flags & BOLD))
1921
if (term->screen.colorBLMode && (flags & BLINK))
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.
1932
extract_bg(unsigned color, unsigned flags)
1934
int bg = (int) ExtractBackground(color);
1936
if (term->screen.colorAttrMode
1937
|| (bg == (int) ExtractForeground(color))) {
1938
if (term->screen.colorRVMode && (flags & INVERSE))
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
1950
* This assumes that fg/bg are equal when we override with one of the special
1954
makeColorPair(int fg, int bg)
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;
1959
return (my_fg << 8) | my_bg;
1961
return (my_fg << 4) | my_bg;
1966
* Using the "current" SGR background, clear a rectangle.
1976
XSetWindowBackground(
1979
getXtermBackground(term->flags, term->cur_background));
1981
XClearArea(screen->display, VWindow(screen),
1982
left, top, width, height, FALSE);
1984
XSetWindowBackground(
1987
getXtermBackground(term->flags, MAXCOLORS));
1989
#endif /* OPT_ISO_COLORS */
1993
* Returns a single 8/16-bit number for the given cell
1996
getXtermCell(TScreen * screen, int row, int col)
1998
unsigned ch = SCRN_BUF_CHARS(screen, row)[col];
1999
if_OPT_WIDE_CHARS(screen, {
2000
ch |= (SCRN_BUF_WIDEC(screen, row)[col] << 8);
2006
getXtermCellComb1(TScreen * screen, int row, int col)
2008
unsigned ch = SCRN_BUF_COM1L(screen, row)[col];
2009
ch |= (SCRN_BUF_COM1H(screen, row)[col] << 8);
2014
getXtermCellComb2(TScreen * screen, int row, int col)
2016
unsigned ch = SCRN_BUF_COM2L(screen, row)[col];
2017
ch |= (SCRN_BUF_COM2H(screen, row)[col] << 8);
2022
* Sets a single 8/16-bit number for the given cell
2025
putXtermCell(TScreen * screen, int row, int col, int ch)
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;
2038
* Add a combining character for the given cell
2041
addXtermCombining(TScreen * screen, int row, int col, unsigned ch)
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;
2054
#ifdef HAVE_CONFIG_H
2055
#ifdef USE_MY_MEMMOVE
2057
my_memmove(char *s1, char *s2, size_t n)
2060
if ((s1 + n > s2) && (s2 + n > s1)) {
2062
static size_t length;
2065
length = (n * 3) / 2;
2067
? realloc(bfr, length)
2070
SysError(ERROR_MMALLOC);
2072
for (j = 0; j < n; j++)
2081
#endif /* USE_MY_MEMMOVE */
2083
#ifndef HAVE_STRERROR
2087
extern char *sys_errlist[];
2088
extern int sys_nerr;
2089
if (n > 0 && n < sys_nerr)
2090
return sys_errlist[n];
2099
if (isascii(ch) && isupper(ch)) { /* lowercasify */
2110
update_keyboard_type(void)
2112
update_delete_del();
2121
set_keyboard_type(xtermKeyboardType type, Bool set)
2123
xtermKeyboardType save = term->keyboard.type;
2126
term->keyboard.type = type;
2128
term->keyboard.type = keyboardIsDefault;
2131
if (save != term->keyboard.type) {
2132
update_keyboard_type();
2137
toggle_keyboard_type(xtermKeyboardType type)
2139
xtermKeyboardType save = term->keyboard.type;
2141
if (term->keyboard.type == type) {
2142
term->keyboard.type = keyboardIsDefault;
2144
term->keyboard.type = type;
2147
if (save != term->keyboard.type) {
2148
update_keyboard_type();
2153
init_keyboard_type(xtermKeyboardType type, Bool set)
2155
static Bool wasSet = False;
2159
fprintf(stderr, "Conflicting keyboard type option (%d/%d)\n",
2160
term->keyboard.type, type);
2162
term->keyboard.type = type;