ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/screen.C
(Generate patch)

Comparing rxvt-unicode/src/screen.C (file contents):
Revision 1.313 by root, Tue Nov 4 14:25:10 2008 UTC vs.
Revision 1.414 by sf-exg, Tue Jan 24 17:05:05 2012 UTC

1/*---------------------------------------------------------------------------* 1/*---------------------------------------------------------------------------*
2 * File: screen.C 2 * File: screen.C
3 *---------------------------------------------------------------------------* 3 *---------------------------------------------------------------------------*
4 * 4 *
5 * Copyright (c) 1997-2001 Geoff Wing <gcw@pobox.com> 5 * Copyright (c) 1997-2001 Geoff Wing <gcw@pobox.com>
6 * Copyright (c) 2003-2007 Marc Lehmann <pcg@goof.com> 6 * Copyright (c) 2003-2007 Marc Lehmann <schmorp@schmorp.de>
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or 10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version. 11 * (at your option) any later version.
28#include "rxvt.h" /* NECESSARY */ 28#include "rxvt.h" /* NECESSARY */
29#include "rxvtperl.h" /* NECESSARY */ 29#include "rxvtperl.h" /* NECESSARY */
30 30
31#include <inttypes.h> 31#include <inttypes.h>
32 32
33#include "salloc.C" // HACK, should be a seperate compile! 33#include "salloc.C" // HACK, should be a separate compile!
34 34
35static inline void
35static inline void fill_text (text_t *start, text_t value, int len) 36fill_text (text_t *start, text_t value, int len)
36{ 37{
37 while (len--) 38 while (len--)
38 *start++ = value; 39 *start++ = value;
39} 40}
40 41
41/* ------------------------------------------------------------------------- */ 42/* ------------------------------------------------------------------------- */
42#define PROP_SIZE 256*1024
43#define PASTE_SIZE 32768
44#define TABSIZE 8 /* default tab size */ 43#define TABSIZE 8 /* default tab size */
45 44
46/* ------------------------------------------------------------------------- * 45/* ------------------------------------------------------------------------- *
47 * GENERAL SCREEN AND SELECTION UPDATE ROUTINES * 46 * GENERAL SCREEN AND SELECTION UPDATE ROUTINES *
48 * ------------------------------------------------------------------------- */ 47 * ------------------------------------------------------------------------- */
143 col--; 142 col--;
144 143
145 rend_t rend = l.r[col] & ~RS_baseattrMask; 144 rend_t rend = l.r[col] & ~RS_baseattrMask;
146 rend = SET_FONT (rend, FONTSET (rend)->find_font (' ')); 145 rend = SET_FONT (rend, FONTSET (rend)->find_font (' '));
147 146
147 l.touch ();
148
148 // found begin, nuke 149 // found start, nuke
149 do { 150 do {
150 l.t[col] = ' '; 151 l.t[col] = ' ';
151 l.r[col] = rend; 152 l.r[col] = rend;
152 col++; 153 col++;
153 } while (col < ncol && l.t[col] == NOCHAR); 154 } while (col < ncol && l.t[col] == NOCHAR);
162{ 163{
163#if ENABLE_OVERLAY 164#if ENABLE_OVERLAY
164 scr_overlay_off (); 165 scr_overlay_off ();
165#endif 166#endif
166 167
167 rvideo_mode = false;
168 view_start = 0; 168 view_start = 0;
169 num_scr = 0; 169 num_scr = 0;
170 170
171 if (ncol == 0) 171 if (ncol == 0)
172 ncol = 80; 172 ncol = 80;
174 if (nrow == 0) 174 if (nrow == 0)
175 nrow = 24; 175 nrow = 24;
176 176
177 if (ncol == prev_ncol && nrow == prev_nrow) 177 if (ncol == prev_ncol && nrow == prev_nrow)
178 return; 178 return;
179
180 if (current_screen != PRIMARY)
181 scr_swap_screen ();
182 179
183 // we need at least two lines for wrapping to work correctly 180 // we need at least two lines for wrapping to work correctly
184 while (nrow + saveLines < 2) 181 while (nrow + saveLines < 2)
185 { 182 {
186 //TODO//FIXME 183 //TODO//FIXME
206 term_start = 0; 203 term_start = 0;
207 204
208 talloc = new rxvt_salloc (ncol * sizeof (text_t)); 205 talloc = new rxvt_salloc (ncol * sizeof (text_t));
209 ralloc = new rxvt_salloc (ncol * sizeof (rend_t)); 206 ralloc = new rxvt_salloc (ncol * sizeof (rend_t));
210 207
211 row_buf = (line_t *)rxvt_calloc (total_rows + nrow, sizeof (line_t)); 208 row_buf = (line_t *)rxvt_calloc (total_rows , sizeof (line_t));
212 drawn_buf = (line_t *)rxvt_calloc (nrow , sizeof (line_t)); 209 drawn_buf = (line_t *)rxvt_calloc (nrow , sizeof (line_t));
213 swap_buf = (line_t *)rxvt_calloc (nrow , sizeof (line_t)); 210 swap_buf = (line_t *)rxvt_calloc (nrow , sizeof (line_t));
214 211
215 for (int row = nrow; row--; ) 212 for (int row = nrow; row--; )
216 { 213 {
239 selection.text = NULL; 236 selection.text = NULL;
240 selection.len = 0; 237 selection.len = 0;
241 selection.op = SELECTION_CLEAR; 238 selection.op = SELECTION_CLEAR;
242 selection.screen = PRIMARY; 239 selection.screen = PRIMARY;
243 selection.clicks = 0; 240 selection.clicks = 0;
241 selection.clip_text = NULL;
242 selection.clip_len = 0;
244 } 243 }
245 else 244 else
246 { 245 {
247 /* 246 /*
248 * add or delete rows as appropriate 247 * add or delete rows as appropriate
276 swap_buf [row].clear (); scr_blank_screen_mem (swap_buf [row], DEFAULT_RSTYLE); 275 swap_buf [row].clear (); scr_blank_screen_mem (swap_buf [row], DEFAULT_RSTYLE);
277 drawn_buf[row].clear (); scr_blank_screen_mem (drawn_buf[row], DEFAULT_RSTYLE); 276 drawn_buf[row].clear (); scr_blank_screen_mem (drawn_buf[row], DEFAULT_RSTYLE);
278 } 277 }
279 278
280 line_t *old_buf = row_buf; 279 line_t *old_buf = row_buf;
281 row_buf = (line_t *)rxvt_calloc (total_rows + nrow, sizeof (line_t)); 280 row_buf = (line_t *)rxvt_calloc (total_rows, sizeof (line_t));
282 281
283 int p = MOD (term_start + prev_nrow, prev_total_rows); // previous row 282 int p = MOD (term_start + prev_nrow, prev_total_rows); // previous row
284 int pend = MOD (term_start + top_row , prev_total_rows); 283 int pend = MOD (term_start + top_row , prev_total_rows);
285 int q = total_rows; // rewrapped row 284 int q = total_rows; // rewrapped row
286 285
287 if (top_row) 286 if (top_row)
288 { 287 {
289 // Re-wrap lines. This is rather ugly, possibly because I am too dumb 288 // Re-wrap lines. This is rather ugly, possibly because I am too dumb
290 // to come up with a lean and mean algorithm. 289 // to come up with a lean and mean algorithm.
290 // TODO: maybe optimise when width didn't change
291 291
292 row_col_t ocur = screen.cur; 292 row_col_t ocur = screen.cur;
293 ocur.row = MOD (term_start + ocur.row, prev_total_rows); 293 ocur.row = MOD (term_start + ocur.row, prev_total_rows);
294 294
295 do 295 do
296 { 296 {
297 p = MOD (p - 1, prev_total_rows); 297 p = MOD (p - 1, prev_total_rows);
298#ifdef DEBUG_STRICT
299 assert (old_buf [MOD (p, prev_total_rows)].t); 298 assert (old_buf [MOD (p, prev_total_rows)].t);
300#endif
301 int plines = 1; 299 int plines = 1;
302 int llen = old_buf [MOD (p, prev_total_rows)].l; 300 int llen = old_buf [MOD (p, prev_total_rows)].l;
303 301
304 while (p != pend && old_buf [MOD (p - 1, prev_total_rows)].is_longer ()) 302 while (p != pend && old_buf [MOD (p - 1, prev_total_rows)].is_longer ())
305 { 303 {
399 delete old_ta; 397 delete old_ta;
400 delete old_ra; 398 delete old_ra;
401 399
402 clamp_it (screen.cur.row, 0, nrow - 1); 400 clamp_it (screen.cur.row, 0, nrow - 1);
403 clamp_it (screen.cur.col, 0, ncol - 1); 401 clamp_it (screen.cur.col, 0, ncol - 1);
402 }
404 403
405 free (tabs); 404 free (tabs);
406 } 405 tabs = (char *)rxvt_malloc (ncol);
406
407 for (int col = ncol; col--; )
408 tabs [col] = col % TABSIZE == 0;
407 409
408 CLEAR_ALL_SELECTION (); 410 CLEAR_ALL_SELECTION ();
409 411
410 prev_nrow = nrow; 412 prev_nrow = nrow;
411 prev_ncol = ncol; 413 prev_ncol = ncol;
412
413 tabs = (char *)rxvt_malloc (ncol);
414
415 for (int col = ncol; --col; )
416 tabs [col] = col % TABSIZE == 0;
417
418 if (current_screen != PRIMARY)
419 scr_swap_screen ();
420 414
421 tt_winch (); 415 tt_winch ();
422 416
423 HOOK_INVOKE ((this, HOOK_RESET, DT_END)); 417 HOOK_INVOKE ((this, HOOK_RESET, DT_END));
424} 418}
436 delete ralloc; ralloc = 0; 430 delete ralloc; ralloc = 0;
437 431
438 free (row_buf); 432 free (row_buf);
439 free (swap_buf); 433 free (swap_buf);
440 free (drawn_buf); 434 free (drawn_buf);
435 row_buf = 0; // signal that we freed all the arrays above
436
441 free (tabs); 437 free (tabs);
442 438 tabs = 0;
443 row_buf = 0; // signal that we freed all the arrays
444 } 439 }
445} 440}
446 441
447/* ------------------------------------------------------------------------- */ 442/* ------------------------------------------------------------------------- */
448/* 443/*
449 * Hard reset 444 * Hard/Soft reset
450 */ 445 */
451void 446void
452rxvt_term::scr_poweron () 447rxvt_term::scr_poweron ()
453{ 448{
454 scr_release (); 449 scr_release ();
455 prev_nrow = prev_ncol = 0; 450 prev_nrow = prev_ncol = 0;
451 rvideo_mode = false;
452 scr_soft_reset ();
456 scr_reset (); 453 scr_reset ();
457 454
458 scr_clear (true); 455 scr_clear (true);
459 scr_refresh (); 456 scr_refresh ();
457}
458
459void
460rxvt_term::scr_soft_reset () NOTHROW
461{
462 /* only affects modes, nothing drastic such as clearing the screen */
463#if ENABLE_OVERLAY
464 scr_overlay_off ();
465#endif
466
467 if (current_screen != PRIMARY)
468 scr_swap_screen ();
469
470 scr_scroll_region (0, MAX_ROWS - 1);
471 scr_rendition (0, ~RS_None);
472 scr_insert_mode (0);
460} 473}
461 474
462/* ------------------------------------------------------------------------- * 475/* ------------------------------------------------------------------------- *
463 * PROCESS SCREEN COMMANDS * 476 * PROCESS SCREEN COMMANDS *
464 * ------------------------------------------------------------------------- */ 477 * ------------------------------------------------------------------------- */
502 } 515 }
503 516
504 /* boundary check in case screen size changed between SAVE and RESTORE */ 517 /* boundary check in case screen size changed between SAVE and RESTORE */
505 min_it (s->cur.row, nrow - 1); 518 min_it (s->cur.row, nrow - 1);
506 min_it (s->cur.col, ncol - 1); 519 min_it (s->cur.col, ncol - 1);
507#ifdef DEBUG_STRICT
508 assert (s->cur.row >= 0); 520 assert (s->cur.row >= 0);
509 assert (s->cur.col >= 0); 521 assert (s->cur.col >= 0);
510#endif
511} 522}
512 523
513void 524void
514rxvt_term::scr_swap_screen () 525rxvt_term::scr_swap_screen () NOTHROW
515{ 526{
516 if (!option (Opt_secondaryScreen)) 527 if (!option (Opt_secondaryScreen))
517 return; 528 return;
518 529
519 for (int i = prev_nrow; i--; ) 530 for (int i = prev_nrow; i--; )
538 return; 549 return;
539 550
540 want_refresh = 1; 551 want_refresh = 1;
541 view_start = 0; 552 view_start = 0;
542 553
543 selection_check (2); /* check for boundary cross */ 554 /* check for boundary cross */
555 row_col_t pos;
556 pos.row = pos.col = 0;
557 if (ROWCOL_IS_BEFORE (selection.beg, pos)
558 && ROWCOL_IS_AFTER (selection.end, pos))
559 CLEAR_SELECTION ();
544 560
545 int i = current_screen; current_screen = scrn; scrn = i; 561 current_screen = scrn;
546 562
547#if NSCREENS 563#if NSCREENS
548 if (option (Opt_secondaryScreen)) 564 if (option (Opt_secondaryScreen))
549 { 565 {
550 num_scr = 0; 566 num_scr = 0;
627 643
628 if (count > 0 644 if (count > 0
629 && row1 == 0 645 && row1 == 0
630 && (current_screen == PRIMARY || option (Opt_secondaryScroll))) 646 && (current_screen == PRIMARY || option (Opt_secondaryScroll)))
631 { 647 {
648 min_it (count, total_rows - (nrow - (row2 + 1)));
649
632 top_row = max (top_row - count, -saveLines); 650 top_row = max (top_row - count, -saveLines);
633
634 // scroll everything up 'count' lines
635 term_start = (term_start + count) % total_rows;
636 651
637 // sever bottommost line 652 // sever bottommost line
638 { 653 {
639 line_t &l = ROW(row2 - count); 654 line_t &l = ROW(row2);
640 l.is_longer (0); 655 l.is_longer (0);
641 l.touch (); 656 l.touch ();
642 } 657 }
643 658
659 // scroll everything up 'count' lines
660 term_start = (term_start + count) % total_rows;
661
662 // now copy lines below the scroll region bottom to the
663 // bottom of the screen again, so they look as if they
664 // hadn't moved.
665 for (int i = nrow; --i > row2; )
666 {
667 line_t &l1 = ROW(i - count);
668 line_t &l2 = ROW(i);
669
670 ::swap (l1, l2);
671 l2.touch ();
672 }
673
644 // erase newly scrolled-in lines 674 // erase newly scrolled-in lines
645 for (int i = count; i--; ) 675 for (int i = count; i--; )
646 { 676 {
647 line_t &l = ROW(nrow - 1 - i); 677 line_t &l = ROW(row2 - i);
648 678
649 // optimize if already cleared, can be significant on slow machines 679 // optimise if already cleared, can be significant on slow machines
650 // could be rolled into scr_blank_screen_mem 680 // could be rolled into scr_blank_screen_mem
651 if (l.r && l.l < ncol - 1 && !((l.r[l.l + 1] ^ rstyle) & (RS_fgMask | RS_bgMask))) 681 if (l.r && l.l < ncol - 1 && !((l.r[l.l + 1] ^ rstyle) & (RS_fgMask | RS_bgMask)))
652 { 682 {
653 scr_blank_line (l, 0, l.l, rstyle); 683 scr_blank_line (l, 0, l.l, rstyle);
654 l.l = 0; 684 l.l = 0;
656 } 686 }
657 else 687 else
658 scr_blank_screen_mem (l, rstyle); 688 scr_blank_screen_mem (l, rstyle);
659 } 689 }
660 690
661 // now copy lines below the scroll region bottom to the
662 // bottom of the screen again, so they look as if they
663 // hadn't moved.
664 for (int i = nrow; --i > row2; )
665 {
666 line_t &l1 = ROW(i - count);
667 line_t &l2 = ROW(i);
668
669 ::swap (l1, l2);
670 l2.touch ();
671 }
672
673 // move and/or clear selection, if any 691 // move and/or clear selection, if any
674 if (selection.op && current_screen == selection.screen) 692 if (selection.op && current_screen == selection.screen
693 && selection.beg.row <= row2)
675 { 694 {
676 selection.beg.row -= count; 695 selection.beg.row -= count;
677 selection.end.row -= count; 696 selection.end.row -= count;
678 selection.mark.row -= count; 697 selection.mark.row -= count;
679 698
680 if (selection.beg.row < top_row 699 selection_check (0);
681 || selection.end.row < top_row
682 || selection.mark.row < top_row)
683 {
684 CLEAR_ALL_SELECTION ();
685 selection.op = SELECTION_CLEAR;
686 }
687 } 700 }
688 701
689 // finally move the view window, if desired 702 // finally move the view window, if desired
690 if (option (Opt_scrollWithBuffer) 703 if (option (Opt_scrollWithBuffer)
691 && view_start != 0 704 && view_start != 0
721 } 734 }
722 735
723 // use a simple and robust scrolling algorithm, this 736 // use a simple and robust scrolling algorithm, this
724 // part of scr_scroll_text is not time-critical. 737 // part of scr_scroll_text is not time-critical.
725 738
739 // sever line above scroll region
740 if (row1)
741 {
742 line_t &l = ROW(row1 - 1);
743 l.is_longer (0);
744 l.touch ();
745 }
746
726 int rows = row2 - row1 + 1; 747 int rows = row2 - row1 + 1;
727 748
728 min_it (count, rows); 749 min_it (count, rows);
729 750
730 line_t *temp_buf = row_buf + total_rows; 751 line_t *temp_buf = rxvt_temp_buf<line_t> (rows);
731 752
732 for (int row = 0; row < rows; row++) 753 for (int row = 0; row < rows; row++)
733 { 754 {
734 temp_buf [row] = ROW(row1 + (row + count + rows) % rows); 755 temp_buf [row] = ROW(row1 + (row + count + rows) % rows);
735 756
737 scr_blank_screen_mem (temp_buf [row], rstyle); 758 scr_blank_screen_mem (temp_buf [row], rstyle);
738 } 759 }
739 760
740 for (int row = 0; row < rows; row++) 761 for (int row = 0; row < rows; row++)
741 ROW(row1 + row) = temp_buf [row]; 762 ROW(row1 + row) = temp_buf [row];
763
764 // sever bottommost line
765 {
766 line_t &l = ROW(row2);
767 l.is_longer (0);
768 l.touch ();
769 }
742 } 770 }
743 771
744 return count; 772 return count;
745} 773}
746 774
752rxvt_term::scr_add_lines (const wchar_t *str, int len, int minlines) NOTHROW 780rxvt_term::scr_add_lines (const wchar_t *str, int len, int minlines) NOTHROW
753{ 781{
754 if (len <= 0) /* sanity */ 782 if (len <= 0) /* sanity */
755 return; 783 return;
756 784
757 unsigned char checksel; 785 bool checksel;
758 unicode_t c; 786 unicode_t c;
759 int ncol = this->ncol; 787 int ncol = this->ncol;
760 const wchar_t *strend = str + len; 788 const wchar_t *strend = str + len;
761 789
762 want_refresh = 1; 790 want_refresh = 1;
775 scr_scroll_text (screen.tscroll, screen.bscroll, minlines); 803 scr_scroll_text (screen.tscroll, screen.bscroll, minlines);
776 screen.cur.row -= minlines; 804 screen.cur.row -= minlines;
777 } 805 }
778 } 806 }
779 807
780#ifdef DEBUG_STRICT
781 assert (screen.cur.col < ncol); 808 assert (screen.cur.col < ncol);
782 assert (screen.cur.row < nrow 809 assert (screen.cur.row < nrow
783 && screen.cur.row >= top_row); 810 && screen.cur.row >= top_row);
784#endif
785 int row = screen.cur.row; 811 int row = screen.cur.row;
786 812
787 checksel = selection.op && current_screen == selection.screen ? 1 : 0; 813 checksel = selection.op && current_screen == selection.screen ? 1 : 0;
788 814
789 line_t *line = &ROW(row); 815 line_t *line = &ROW(row);
790 816
791 while (str < strend) 817 while (str < strend)
792 { 818 {
793 c = (unicode_t)*str++; // convert to rxvt-unicodes representation 819 c = (unicode_t)*str++; // convert to rxvt-unicodes representation
794 820
795 if (expect_false (c < 0x20)) 821 if (ecb_unlikely (c < 0x20))
796 if (c == C0_LF) 822 if (c == C0_LF)
797 { 823 {
798 max_it (line->l, screen.cur.col); 824 max_it (line->l, screen.cur.col);
799 825
800 screen.flags &= ~Screen_WrapNext; 826 screen.flags &= ~Screen_WrapNext;
819 { 845 {
820 scr_tab (1, true); 846 scr_tab (1, true);
821 continue; 847 continue;
822 } 848 }
823 849
824 if (expect_false ( 850 if (ecb_unlikely (
825 checksel /* see if we're writing within selection */ 851 checksel /* see if we're writing within selection */
826 && !ROWCOL_IS_BEFORE (screen.cur, selection.beg) 852 && !ROWCOL_IS_BEFORE (screen.cur, selection.beg)
827 && ROWCOL_IS_BEFORE (screen.cur, selection.end) 853 && ROWCOL_IS_BEFORE (screen.cur, selection.end)
828 )) 854 ))
829 { 855 {
834 * should be a similar check. 860 * should be a similar check.
835 */ 861 */
836 CLEAR_SELECTION (); 862 CLEAR_SELECTION ();
837 } 863 }
838 864
839 if (expect_false (screen.flags & Screen_WrapNext)) 865 if (ecb_unlikely (screen.flags & Screen_WrapNext))
840 { 866 {
841 scr_do_wrap (); 867 scr_do_wrap ();
842 868
843 line->l = ncol; 869 line->l = ncol;
844 line->is_longer (1); 870 line->is_longer (1);
846 row = screen.cur.row; 872 row = screen.cur.row;
847 line = &ROW(row); /* _must_ refresh */ 873 line = &ROW(row); /* _must_ refresh */
848 } 874 }
849 875
850 // some utf-8 decoders "decode" surrogate characters: let's fix this. 876 // some utf-8 decoders "decode" surrogate characters: let's fix this.
851 if (expect_false (IN_RANGE_INC (c, 0xd800, 0xdfff))) 877 if (ecb_unlikely (IN_RANGE_INC (c, 0xd800, 0xdfff)))
852 c = 0xfffd; 878 c = 0xfffd;
853 879
854 // rely on wcwidth to tell us the character width, do wcwidth before 880 // rely on wcwidth to tell us the character width, do wcwidth before
855 // further replacements, as wcwidth might return -1 for the line 881 // further replacements, as wcwidth might return -1 for the line
856 // drawing characters below as they might be invalid in the current 882 // drawing characters below as they might be invalid in the current
857 // locale. 883 // locale.
858 int width = WCWIDTH (c); 884 int width = WCWIDTH (c);
859 885
860 if (expect_false (charsets [screen.charset] == '0')) // DEC SPECIAL 886 if (ecb_unlikely (charsets [screen.charset] == '0')) // DEC SPECIAL
861 { 887 {
862 // vt100 special graphics and line drawing 888 // vt100 special graphics and line drawing
863 // 5f-7e standard vt100 889 // 5f-7e standard vt100
864 // 40-5e rxvt extension for extra curses acs chars 890 // 40-5e rxvt extension for extra curses acs chars
865 static uint16_t vt100_0[62] = { // 41 .. 7e 891 static uint16_t vt100_0[62] = { // 41 .. 7e
878 c = vt100_0[c - 0x41]; 904 c = vt100_0[c - 0x41];
879 width = 1; // vt100 line drawing characters are always single-width 905 width = 1; // vt100 line drawing characters are always single-width
880 } 906 }
881 } 907 }
882 908
883 if (expect_false (screen.flags & Screen_Insert)) 909 if (ecb_unlikely (screen.flags & Screen_Insert))
884 scr_insdel_chars (width, INSERT); 910 scr_insdel_chars (width, INSERT);
885 911
886 if (width != 0) 912 if (width != 0)
887 { 913 {
888#if !UNICODE_3 914#if !UNICODE_3
893# else 919# else
894 c = 0xfffd; 920 c = 0xfffd;
895# endif 921# endif
896#endif 922#endif
897 923
924 rend_t rend = SET_FONT (rstyle, FONTSET (rstyle)->find_font (c));
925
926 // if the character doesn't fit into the remaining columns...
927 if (ecb_unlikely (screen.cur.col > ncol - width && ncol >= width))
928 {
929 if (screen.flags & Screen_Autowrap)
930 {
931 // ... artificially enlargen the previous one
932 c = NOCHAR;
933 // and try the same character next loop iteration
934 --str;
935 }
936 else
937 screen.cur.col = ncol - width;
938 }
939
898 // nuke the character at this position, if required 940 // nuke the character at this position, if required
899 if (expect_false ( 941 // due to wonderful coincidences everywhere else in this loop
942 // we never have to check for overwriting a wide char itself,
943 // only its tail.
900 line->t[screen.cur.col] == NOCHAR 944 if (ecb_unlikely (line->t[screen.cur.col] == NOCHAR))
901 || (screen.cur.col < ncol - 1
902 && line->t[screen.cur.col + 1] == NOCHAR)
903 ))
904 scr_kill_char (*line, screen.cur.col); 945 scr_kill_char (*line, screen.cur.col);
905
906 rend_t rend = SET_FONT (rstyle, FONTSET (rstyle)->find_font (c));
907
908 // if the character doesn't fit into the remaining columns...
909 if (expect_false (screen.cur.col > ncol - width && ncol >= width))
910 {
911 // ...output spaces
912 c = ' ';
913 // and try the same character next loop iteration
914 --str;
915 }
916 946
917 line->touch (); 947 line->touch ();
918 948
919 do 949 do
920 { 950 {
921 line->t[screen.cur.col] = c; 951 line->t[screen.cur.col] = c;
922 line->r[screen.cur.col] = rend; 952 line->r[screen.cur.col] = rend;
923 953
924 if (expect_true (screen.cur.col < ncol - 1)) 954 if (ecb_likely (screen.cur.col < ncol - 1))
925 screen.cur.col++; 955 screen.cur.col++;
926 else 956 else
927 { 957 {
928 line->l = ncol; 958 line->l = ncol;
929 if (screen.flags & Screen_Autowrap) 959 if (screen.flags & Screen_Autowrap)
930 screen.flags |= Screen_WrapNext; 960 screen.flags |= Screen_WrapNext;
931 break; 961
962 goto end_of_line;
932 } 963 }
933 964
934 c = NOCHAR; 965 c = NOCHAR;
935 } 966 }
936 while (expect_false (--width > 0)); 967 while (ecb_unlikely (--width > 0));
937 968
938 // pad with spaces when overwriting wide character with smaller one 969 // pad with spaces when overwriting wide character with smaller one
939 if (expect_false (!width)) 970 for (int c = screen.cur.col; ecb_unlikely (c < ncol && line->t[c] == NOCHAR); c++)
940 { 971 {
941 line->touch ();
942
943 for (int c = screen.cur.col; c < ncol && line->t[c] == NOCHAR; c++)
944 {
945 line->t[c] = ' '; 972 line->t[c] = ' ';
946 line->r[c] = rend; 973 line->r[c] = rend;
947 }
948 } 974 }
975
976end_of_line:
977 ;
949 } 978 }
950#if ENABLE_COMBINING 979#if ENABLE_COMBINING
951 else // width == 0 980 else // width == 0
952 { 981 {
953 if (c != 0xfeff) // ignore BOM 982 if (c != 0xfeff) // ignore BOM
993#endif 1022#endif
994 } 1023 }
995 1024
996 max_it (line->l, screen.cur.col); 1025 max_it (line->l, screen.cur.col);
997 1026
998#ifdef DEBUG_STRICT
999 assert (screen.cur.row >= 0); 1027 assert (screen.cur.row >= 0);
1000#endif
1001} 1028}
1002 1029
1003/* ------------------------------------------------------------------------- */ 1030/* ------------------------------------------------------------------------- */
1004/* 1031/*
1005 * Process Backspace. Move back the cursor back a position, wrap if have to 1032 * Process Backspace. Move back the cursor back a position, wrap if have to
1018 1045
1019 want_refresh = 1; 1046 want_refresh = 1;
1020#endif 1047#endif
1021 } 1048 }
1022 } 1049 }
1050 else if (screen.flags & Screen_WrapNext)
1051 screen.flags &= ~Screen_WrapNext;
1023 else 1052 else
1024 scr_gotorc (0, -1, RELATIVE); 1053 scr_gotorc (0, -1, RELATIVE);
1025} 1054}
1026 1055
1027/* ------------------------------------------------------------------------- */ 1056/* ------------------------------------------------------------------------- */
1283 scr_blank_line (line, col, num, rstyle); 1312 scr_blank_line (line, col, num, rstyle);
1284} 1313}
1285 1314
1286/* ------------------------------------------------------------------------- */ 1315/* ------------------------------------------------------------------------- */
1287/* 1316/*
1288 * Erase part of whole of the screen 1317 * Erase part or whole of the screen
1289 * XTERM_SEQ: Clear screen after cursor : ESC [ 0 J 1318 * XTERM_SEQ: Clear screen after cursor : ESC [ 0 J
1290 * XTERM_SEQ: Clear screen before cursor: ESC [ 1 J 1319 * XTERM_SEQ: Clear screen before cursor: ESC [ 1 J
1291 * XTERM_SEQ: Clear whole screen : ESC [ 2 J 1320 * XTERM_SEQ: Clear whole screen : ESC [ 2 J
1292 */ 1321 */
1293void 1322void
1302 ZERO_SCROLLBACK (); 1331 ZERO_SCROLLBACK ();
1303 1332
1304 switch (mode) 1333 switch (mode)
1305 { 1334 {
1306 case 0: /* erase to end of screen */ 1335 case 0: /* erase to end of screen */
1307 selection_check (1);
1308 scr_erase_line (0); 1336 scr_erase_line (0);
1309 row = screen.cur.row + 1; /* possible OOB */ 1337 row = screen.cur.row + 1; /* possible OOB */
1310 num = nrow - row; 1338 num = nrow - row;
1311 break; 1339 break;
1312 case 1: /* erase to beginning of screen */ 1340 case 1: /* erase to beginning of screen */
1313 selection_check (3);
1314 scr_erase_line (1); 1341 scr_erase_line (1);
1315 row = 0; 1342 row = 0;
1316 num = screen.cur.row; 1343 num = screen.cur.row;
1317 break; 1344 break;
1318 case 2: /* erase whole screen */ 1345 case 2: /* erase whole screen */
1319 selection_check (3);
1320 row = 0; 1346 row = 0;
1321 num = nrow; 1347 num = nrow;
1322 break; 1348 break;
1323 default: 1349 default:
1324 return; 1350 return;
1333 if (row >= nrow) /* Out Of Bounds */ 1359 if (row >= nrow) /* Out Of Bounds */
1334 return; 1360 return;
1335 1361
1336 min_it (num, nrow - row); 1362 min_it (num, nrow - row);
1337 1363
1338 /*TODO: the xlceararea/xfillrectangle below don't take scroll offste into account, ask mikachu for details */
1339 if (rstyle & (RS_RVid | RS_Uline)) 1364 if (rstyle & (RS_Blink | RS_RVid | RS_Uline))
1340 ren = (rend_t) ~RS_None; 1365 ren = (rend_t) ~RS_None;
1341 else if (GET_BASEBG (rstyle) == Color_bg) 1366 else if (GET_BASEBG (rstyle) == Color_bg)
1342 { 1367 {
1343 ren = DEFAULT_RSTYLE; 1368 ren = DEFAULT_RSTYLE;
1344 1369
1345 if (mapped) 1370 if (mapped)
1346 XClearArea (dpy, vt, 0, 1371 XClearArea (dpy, vt, 0,
1347 Row2Pixel (row), (unsigned int)width, 1372 Row2Pixel (row - view_start), (unsigned int)vt_width,
1348 (unsigned int)Height2Pixel (num), False); 1373 (unsigned int)Height2Pixel (num), False);
1349 } 1374 }
1350 else 1375 else
1351 { 1376 {
1352 ren = rstyle & (RS_fgMask | RS_bgMask); 1377 ren = rstyle & (RS_fgMask | RS_bgMask);
1353 1378
1379 if (mapped)
1380 {
1354 gcvalue.foreground = pix_colors[bgcolor_of (rstyle)]; 1381 gcvalue.foreground = pix_colors[bgcolor_of (rstyle)];
1355 XChangeGC (dpy, gc, GCForeground, &gcvalue); 1382 XChangeGC (dpy, gc, GCForeground, &gcvalue);
1356 XFillRectangle (dpy, vt, gc, 1383 XFillRectangle (dpy, vt, gc,
1357 0, Row2Pixel (row), 1384 0, Row2Pixel (row - view_start),
1358 (unsigned int)width, 1385 (unsigned int)vt_width,
1359 (unsigned int)Height2Pixel (num)); 1386 (unsigned int)Height2Pixel (num));
1360 gcvalue.foreground = pix_colors[Color_fg]; 1387 gcvalue.foreground = pix_colors[Color_fg];
1361 XChangeGC (dpy, gc, GCForeground, &gcvalue); 1388 XChangeGC (dpy, gc, GCForeground, &gcvalue);
1389 }
1362 } 1390 }
1363 1391
1364 for (; num--; row++) 1392 for (; num--; row++)
1365 { 1393 {
1366 scr_blank_screen_mem (ROW(row), rstyle); 1394 scr_blank_screen_mem (ROW(row), rstyle);
1395
1396 if (row - view_start < nrow)
1367 scr_blank_line (drawn_buf [row], 0, ncol, ren); 1397 scr_blank_line (drawn_buf [row - view_start], 0, ncol, ren);
1368 } 1398 }
1369} 1399}
1370 1400
1371#if !ENABLE_MINIMAL 1401#if !ENABLE_MINIMAL
1372void 1402void
1391 1421
1392 want_refresh = 1; 1422 want_refresh = 1;
1393 ZERO_SCROLLBACK (); 1423 ZERO_SCROLLBACK ();
1394 1424
1395 num_scr_allow = 0; 1425 num_scr_allow = 0;
1396 selection_check (3); 1426
1427 row_col_t pos;
1428 pos.row = pos.col = 0;
1429 if (ROWCOL_IS_AFTER (selection.end, pos))
1430 CLEAR_SELECTION ();
1397 1431
1398 fs = SET_FONT (rstyle, FONTSET (rstyle)->find_font ('E')); 1432 fs = SET_FONT (rstyle, FONTSET (rstyle)->find_font ('E'));
1399 for (int row = nrow; row--; ) 1433 for (int row = nrow; row--; )
1400 { 1434 {
1401 line_t &line = ROW(row); 1435 line_t &line = ROW(row);
1446 * Insert/Delete <count> characters from the current position 1480 * Insert/Delete <count> characters from the current position
1447 */ 1481 */
1448void 1482void
1449rxvt_term::scr_insdel_chars (int count, int insdel) NOTHROW 1483rxvt_term::scr_insdel_chars (int count, int insdel) NOTHROW
1450{ 1484{
1451 int col, row;
1452 rend_t tr;
1453
1454 want_refresh = 1; 1485 want_refresh = 1;
1455 ZERO_SCROLLBACK (); 1486 ZERO_SCROLLBACK ();
1456 1487
1457 if (count <= 0) 1488 if (count <= 0)
1458 return; 1489 return;
1460 scr_do_wrap (); 1491 scr_do_wrap ();
1461 1492
1462 selection_check (1); 1493 selection_check (1);
1463 min_it (count, ncol - screen.cur.col); 1494 min_it (count, ncol - screen.cur.col);
1464 1495
1465 row = screen.cur.row; 1496 int row = screen.cur.row;
1466 1497
1467 line_t *line = &ROW(row); 1498 line_t *line = &ROW(row);
1468 1499
1469 line->touch (); 1500 line->touch ();
1470 line->is_longer (0); 1501 line->is_longer (0);
1471 1502
1503 // nuke wide spanning the start
1504 if (line->t[screen.cur.col] == NOCHAR)
1505 scr_kill_char (*line, screen.cur.col);
1506
1472 switch (insdel) 1507 switch (insdel)
1473 { 1508 {
1474 case INSERT: 1509 case INSERT:
1475 for (col = ncol - 1; (col - count) >= screen.cur.col; col--) 1510 line->l = min (line->l + count, ncol);
1511
1512 if (line->t[screen.cur.col] == NOCHAR)
1513 scr_kill_char (*line, screen.cur.col);
1514
1515 for (int col = ncol - 1; (col - count) >= screen.cur.col; col--)
1476 { 1516 {
1477 line->t[col] = line->t[col - count]; 1517 line->t[col] = line->t[col - count];
1478 line->r[col] = line->r[col - count]; 1518 line->r[col] = line->r[col - count];
1479 } 1519 }
1480
1481 line->l = min (line->l + count, ncol);
1482 1520
1483 if (selection.op && current_screen == selection.screen 1521 if (selection.op && current_screen == selection.screen
1484 && ROWCOL_IN_ROW_AT_OR_AFTER (selection.beg, screen.cur)) 1522 && ROWCOL_IN_ROW_AT_OR_AFTER (selection.beg, screen.cur))
1485 { 1523 {
1486 if (selection.end.row != screen.cur.row 1524 if (selection.end.row != screen.cur.row
1501 case ERASE: 1539 case ERASE:
1502 screen.cur.col += count; /* don't worry if > ncol */ 1540 screen.cur.col += count; /* don't worry if > ncol */
1503 selection_check (1); 1541 selection_check (1);
1504 screen.cur.col -= count; 1542 screen.cur.col -= count;
1505 1543
1544 // nuke wide char after the end
1545 if (screen.cur.col + count < ncol && line->t[screen.cur.col + count] == NOCHAR)
1546 scr_kill_char (*line, screen.cur.col + count);
1547
1506 scr_blank_line (*line, screen.cur.col, count, rstyle); 1548 scr_blank_line (*line, screen.cur.col, count, rstyle);
1507 break; 1549 break;
1508 1550
1509 case DELETE: 1551 case DELETE:
1510 tr = line->r[ncol - 1] & (RS_fgMask | RS_bgMask | RS_baseattrMask); 1552 line->l = max (line->l - count, 0);
1511 1553
1554 // nuke wide char spanning the end
1555 if (screen.cur.col + count < ncol && line->t[screen.cur.col + count] == NOCHAR)
1556 scr_kill_char (*line, screen.cur.col + count);
1557
1512 for (col = screen.cur.col; (col + count) < ncol; col++) 1558 for (int col = screen.cur.col; (col + count) < ncol; col++)
1513 { 1559 {
1514 line->t[col] = line->t[col + count]; 1560 line->t[col] = line->t[col + count];
1515 line->r[col] = line->r[col + count]; 1561 line->r[col] = line->r[col + count];
1516 } 1562 }
1517 1563
1518 line->l = max (line->l - count, 0);
1519 scr_blank_line (*line, ncol - count, count, tr); 1564 scr_blank_line (*line, ncol - count, count, rstyle);
1520 1565
1521 if (selection.op && current_screen == selection.screen 1566 if (selection.op && current_screen == selection.screen
1522 && ROWCOL_IN_ROW_AT_OR_AFTER (selection.beg, screen.cur)) 1567 && ROWCOL_IN_ROW_AT_OR_AFTER (selection.beg, screen.cur))
1523 { 1568 {
1524 if (selection.end.row != screen.cur.row 1569 if (selection.end.row != screen.cur.row
1660 { 1705 {
1661 rvideo_state = on; 1706 rvideo_state = on;
1662 1707
1663 ::swap (pix_colors[Color_fg], pix_colors[Color_bg]); 1708 ::swap (pix_colors[Color_fg], pix_colors[Color_bg]);
1664#ifdef HAVE_BG_PIXMAP 1709#ifdef HAVE_BG_PIXMAP
1665 if (bgPixmap.pixmap == None) 1710 if (bg_pixmap == None)
1666#endif 1711#endif
1667 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]); 1712 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
1668 1713
1669 XGCValues gcvalue; 1714 XGCValues gcvalue;
1670 gcvalue.foreground = pix_colors[Color_fg]; 1715 gcvalue.foreground = pix_colors[Color_fg];
1814 for (i = PART_BEG; i < RC_COUNT; i++) 1859 for (i = PART_BEG; i < RC_COUNT; i++)
1815 { 1860 {
1816 min_it (rc[i].col, ncol - 1); 1861 min_it (rc[i].col, ncol - 1);
1817 min_it (rc[i].row, nrow - 1); 1862 min_it (rc[i].row, nrow - 1);
1818 } 1863 }
1819// TODO: this line somehow causes segfault if scr_expose() is called just after resize 1864
1820 for (i = rc[PART_BEG].row; i <= rc[PART_END].row; i++) 1865 for (i = rc[PART_BEG].row; i <= rc[PART_END].row; i++)
1821 fill_text (&drawn_buf[i].t[rc[PART_BEG].col], 0, rc[PART_END].col - rc[PART_BEG].col + 1); 1866 fill_text (&drawn_buf[i].t[rc[PART_BEG].col], 0, rc[PART_END].col - rc[PART_BEG].col + 1);
1822 1867
1823 num_scr_allow = 0; 1868 num_scr_allow = 0;
1824 1869
1831 * Refresh the entire screen 1876 * Refresh the entire screen
1832 */ 1877 */
1833void 1878void
1834rxvt_term::scr_touch (bool refresh) NOTHROW 1879rxvt_term::scr_touch (bool refresh) NOTHROW
1835{ 1880{
1836 scr_expose (0, 0, width, height, refresh); 1881 scr_expose (0, 0, vt_width, vt_height, refresh);
1837} 1882}
1838 1883
1839/* ------------------------------------------------------------------------- */ 1884/* ------------------------------------------------------------------------- */
1840/* 1885/*
1841 * Move the display so that the line represented by scrollbar value Y is at 1886 * Move the display so that the line represented by scrollbar value Y is at
1897 1942
1898# ifndef NO_MAPALERT 1943# ifndef NO_MAPALERT
1899# ifdef MAPALERT_OPTION 1944# ifdef MAPALERT_OPTION
1900 if (option (Opt_mapAlert)) 1945 if (option (Opt_mapAlert))
1901# endif 1946# endif
1902 XMapWindow (dpy, parent[0]); 1947 XMapWindow (dpy, parent);
1903# endif 1948# endif
1904 1949
1905# if ENABLE_FRILLS 1950# if ENABLE_FRILLS
1906 if (option (Opt_urgentOnBell)) 1951 if (option (Opt_urgentOnBell))
1907 set_urgency (1); 1952 set_urgency (1);
1915 1960
1916 bell_ev.start (VISUAL_BELL_DURATION); 1961 bell_ev.start (VISUAL_BELL_DURATION);
1917 } 1962 }
1918 else 1963 else
1919 XBell (dpy, 0); 1964 XBell (dpy, 0);
1965 HOOK_INVOKE ((this, HOOK_BELL, DT_END));
1920#endif 1966#endif
1921} 1967}
1922 1968
1923/* ------------------------------------------------------------------------- */ 1969/* ------------------------------------------------------------------------- */
1924/* ARGSUSED */
1925void 1970void
1926rxvt_term::scr_printscreen (int fullhist) NOTHROW 1971rxvt_term::scr_printscreen (int fullhist) NOTHROW
1927{ 1972{
1928#ifdef PRINTPIPE 1973#ifdef PRINTPIPE
1929 int nrows, row_start; 1974 int nrows, row_start;
1943 row_start = view_start; 1988 row_start = view_start;
1944 } 1989 }
1945 1990
1946 wctomb (0, 0); 1991 wctomb (0, 0);
1947 1992
1948 for (int r1 = 0; r1 < nrows; r1++) 1993 for (int r1 = row_start; r1 < row_start + nrows; r1++)
1949 { 1994 {
1950 text_t *tp = ROW(r1).t; 1995 text_t *tp = ROW(r1).t;
1951 int len = ROW(r1).l; 1996 int len = ROW(r1).l;
1952 1997
1953 for (int i = len >= 0 ? len : ncol - 1; i--; ) //TODO//FIXME//LEN 1998 for (int i = len >= 0 ? len : ncol - 1; i--; ) //TODO//FIXME//LEN
1982 * screen.text/screen.rend contain what the screen will change to. 2027 * screen.text/screen.rend contain what the screen will change to.
1983 */ 2028 */
1984void 2029void
1985rxvt_term::scr_refresh () NOTHROW 2030rxvt_term::scr_refresh () NOTHROW
1986{ 2031{
1987 unsigned char have_bg,
1988 showcursor; /* show the cursor */
1989 int16_t col, row, /* column/row we're processing */ 2032 int16_t col, row, /* column/row we're processing */
1990 ocrow; /* old cursor row */ 2033 ocrow; /* old cursor row */
1991 int i; /* tmp */ 2034 int i; /* tmp */
1992#ifndef NO_CURSORCOLOR 2035#ifndef NO_CURSORCOLOR
1993 rend_t cc1; /* store colours at cursor position (s) */ 2036 rend_t cc1; /* store colours at cursor position (s) */
2004 /* 2047 /*
2005 * A: set up vars 2048 * A: set up vars
2006 */ 2049 */
2007 refresh_count = 0; 2050 refresh_count = 0;
2008 2051
2052 unsigned int old_screen_flags = screen.flags;
2009 have_bg = 0; 2053 bool have_bg = 0;
2010#ifdef HAVE_BG_PIXMAP 2054#ifdef HAVE_BG_PIXMAP
2011 have_bg = bgPixmap.pixmap != None; 2055 have_bg = bg_pixmap != None;
2012#endif 2056#endif
2013 ocrow = oldcursor.row; /* is there an old outline cursor on screen? */ 2057 ocrow = oldcursor.row; /* is there an old outline cursor on screen? */
2014 2058
2015 /* 2059 /*
2016 * B: reverse any characters which are selected 2060 * B: reverse any characters which are selected
2017 */ 2061 */
2018 scr_reverse_selection (); 2062 scr_reverse_selection ();
2019 2063
2064 HOOK_INVOKE ((this, HOOK_REFRESH_BEGIN, DT_END));
2065#if ENABLE_OVERLAY
2066 scr_swap_overlay ();
2067#endif
2068
2069 bool showcursor = screen.flags & Screen_VisibleCursor;
2070
2020 /* 2071 /*
2021 * C: set the cursor character (s) 2072 * C: set the cursor character (s)
2022 */ 2073 */
2023 { 2074 {
2024 unsigned char setoldcursor; 2075 bool setoldcursor;
2025 2076
2026 showcursor = (screen.flags & Screen_VisibleCursor);
2027#ifdef CURSOR_BLINK 2077#ifdef CURSOR_BLINK
2028 if (hidden_cursor) 2078 if (hidden_cursor)
2029 showcursor = 0; 2079 showcursor = 0;
2030#endif 2080#endif
2031 2081
2059 ccol2 = bgcolor_of (rstyle); 2109 ccol2 = bgcolor_of (rstyle);
2060#else 2110#else
2061 ccol2 = Color_bg; 2111 ccol2 = Color_bg;
2062#endif 2112#endif
2063 2113
2064 if (showcursor && focus) 2114 if (focus)
2065 { 2115 {
2066 if (option (Opt_cursorUnderline)) 2116 if (option (Opt_cursorUnderline))
2067 *crp ^= RS_Uline; 2117 *crp ^= RS_Uline;
2068 else 2118 else
2069 { 2119 {
2104 oldcursor.col = screen.cur.col; 2154 oldcursor.col = screen.cur.col;
2105 } 2155 }
2106 } 2156 }
2107 } 2157 }
2108 2158
2109 HOOK_INVOKE ((this, HOOK_REFRESH_BEGIN, DT_END));
2110#if ENABLE_OVERLAY
2111 scr_swap_overlay ();
2112#endif
2113
2114#ifndef NO_SLOW_LINK_SUPPORT 2159#ifndef NO_SLOW_LINK_SUPPORT
2115 /* 2160 /*
2116 * D: CopyArea pass - very useful for slower links 2161 * D: CopyArea pass - very useful for slower links
2117 * This has been deliberately kept simple. 2162 * This has been deliberately kept simple.
2118 */ 2163 */
2122 { 2167 {
2123 int16_t nits; 2168 int16_t nits;
2124 int i = num_scr; 2169 int i = num_scr;
2125 int j; 2170 int j;
2126 int len, wlen; 2171 int len, wlen;
2127 dLocal (int, num_scr);
2128 2172
2129 j = nrow; 2173 j = nrow;
2130 wlen = len = -1; 2174 wlen = len = -1;
2131 row = i > 0 ? 0 : j - 1; 2175 row = i > 0 ? 0 : j - 1;
2132 2176
2207 continue; 2251 continue;
2208 2252
2209 // redraw one or more characters 2253 // redraw one or more characters
2210 2254
2211 // seek to the beginning of wide characters 2255 // seek to the beginning of wide characters
2212 while (expect_false (stp[col] == NOCHAR && col > 0)) 2256 while (ecb_unlikely (stp[col] == NOCHAR && col > 0))
2213 --col; 2257 --col;
2214 2258
2215 rend_t rend = srp[col]; /* screen rendition (target rendtion) */ 2259 rend_t rend = srp[col]; /* screen rendition (target rendition) */
2216 text_t *text = stp + col; 2260 text_t *text = stp + col;
2217 int count = 1; 2261 int count = 1;
2218 2262
2219 dtp[col] = stp[col]; 2263 dtp[col] = stp[col];
2220 drp[col] = rend; 2264 drp[col] = rend;
2224 for (i = 0; ++col < ncol; ) 2268 for (i = 0; ++col < ncol; )
2225 { 2269 {
2226 if (stp[col] == NOCHAR) 2270 if (stp[col] == NOCHAR)
2227 { 2271 {
2228 dtp[col] = stp[col]; 2272 dtp[col] = stp[col];
2229 drp[col] = rend; 2273 drp[col] = srp[col];
2274
2230 count++; 2275 count++;
2231 i++; 2276 i++;
2232 2277
2233 continue; 2278 continue;
2234 } 2279 }
2254 2299
2255 col--; /* went one too far. move back */ 2300 col--; /* went one too far. move back */
2256 count -= i; /* dump any matching trailing chars */ 2301 count -= i; /* dump any matching trailing chars */
2257 2302
2258 // sometimes we optimize away the trailing NOCHAR's, add them back 2303 // sometimes we optimize away the trailing NOCHAR's, add them back
2259 while (expect_false (i && text[count] == NOCHAR)) 2304 while (ecb_unlikely (i && text[count] == NOCHAR))
2260 count++, i--; 2305 count++, i--;
2261 2306
2262 /* 2307 /*
2263 * Determine the attributes for the string 2308 * Determine the attributes for the string
2264 */ 2309 */
2265 int fore = fgcolor_of (rend); // desired foreground 2310 int fore = fgcolor_of (rend); // desired foreground
2266 int back = bgcolor_of (rend); // desired background 2311 int back = bgcolor_of (rend); // desired background
2267 2312
2268 // only do special processing if any attributes are set, which is unlikely 2313 // only do special processing if any attributes are set, which is unlikely
2269 if (expect_false (rend & (RS_Bold | RS_Italic | RS_Uline | RS_RVid | RS_Blink | RS_Careful))) 2314 if (ecb_unlikely (rend & (RS_baseattrMask | RS_Careful | RS_Sel)))
2270 { 2315 {
2271 bool invert = rend & RS_RVid; 2316 bool invert = rend & RS_RVid;
2272 2317
2273#ifndef NO_BOLD_UNDERLINE_REVERSE 2318#ifndef NO_BOLD_UNDERLINE_REVERSE
2274 if (rend & RS_Bold && fore == Color_fg) 2319 if (rend & RS_Bold && fore == Color_fg)
2293 2338
2294 if (rend & RS_Uline && fore == Color_fg && ISSET_PIXCOLOR (Color_UL)) 2339 if (rend & RS_Uline && fore == Color_fg && ISSET_PIXCOLOR (Color_UL))
2295 fore = Color_UL; 2340 fore = Color_UL;
2296#endif 2341#endif
2297 2342
2343#ifdef OPTION_HC
2344 if (rend & RS_Sel)
2345 {
2346 /* invert the column if no highlightColor is set or it is the
2347 * current cursor column */
2348 if (!(showcursor && row == screen.cur.row && text - stp == screen.cur.col)
2349 && ISSET_PIXCOLOR (Color_HC))
2350 {
2351 if (ISSET_PIXCOLOR (Color_HTC))
2352 fore = Color_HTC;
2353 // if invert is 0 reverse video is set so we use bg color as fg color
2354 else if (!invert)
2355 fore = back;
2356
2357 back = Color_HC;
2358 invert = 0;
2359 }
2360 }
2361#endif
2362
2298 if (invert) 2363 if (invert)
2299 { 2364 {
2300#ifdef OPTION_HC
2301 if ((showcursor && row == screen.cur.row && text - stp == screen.cur.col)
2302 || !ISSET_PIXCOLOR (Color_HC))
2303#endif
2304 /* invert the column if no highlightColor is set or it is the
2305 * current cursor column */
2306 ::swap (fore, back); 2365 ::swap (fore, back);
2307#ifdef OPTION_HC
2308 else if (ISSET_PIXCOLOR (Color_HC))
2309 back = Color_HC;
2310#endif
2311 2366
2312#ifndef NO_BOLD_UNDERLINE_REVERSE 2367#ifndef NO_BOLD_UNDERLINE_REVERSE
2313# ifndef OPTION_HC
2314 if (ISSET_PIXCOLOR (Color_RV))
2315 back = Color_RV;
2316# endif
2317 if (fore == back) 2368 if (fore == back)
2318 { 2369 {
2319 fore = Color_bg; 2370 fore = Color_bg;
2320 back = Color_fg; 2371 back = Color_fg;
2321 } 2372 }
2357 /* 2408 /*
2358 * Actually do the drawing of the string here 2409 * Actually do the drawing of the string here
2359 */ 2410 */
2360 rxvt_font *font = (*fontset[GET_STYLE (rend)])[GET_FONT (rend)]; 2411 rxvt_font *font = (*fontset[GET_STYLE (rend)])[GET_FONT (rend)];
2361 2412
2362 if (expect_true (have_bg && back == Color_bg)) 2413 if (ecb_likely (have_bg && back == Color_bg))
2363 { 2414 {
2364 // this is very ugly, maybe push it into ->draw? 2415 // this is very ugly, maybe push it into ->draw?
2365 2416
2366 for (i = 0; i < count; i++) /* don't draw empty strings */ 2417 for (i = 0; i < count; i++) /* don't draw empty strings */
2367 if (text[i] != ' ') 2418 if (text[i] != ' ')
2374 did_clear: ; 2425 did_clear: ;
2375 } 2426 }
2376 else 2427 else
2377 font->draw (*drawable, xpixel, ypixel, text, count, fore, back); 2428 font->draw (*drawable, xpixel, ypixel, text, count, fore, back);
2378 2429
2379 if (expect_false (rend & RS_Uline && font->descent > 1 && fore != back)) 2430 if (ecb_unlikely (rend & RS_Uline && font->descent > 1 && fore != back))
2380 { 2431 {
2381#if ENABLE_FRILLS 2432#if ENABLE_FRILLS
2382 if (ISSET_PIXCOLOR (Color_underline)) 2433 if (ISSET_PIXCOLOR (Color_underline))
2383 XSetForeground (dpy, gc, pix_colors[Color_underline]); 2434 XSetForeground (dpy, gc, pix_colors[Color_underline]);
2384 else 2435 else
2389 xpixel, ypixel + font->ascent + 1, 2440 xpixel, ypixel + font->ascent + 1,
2390 xpixel + Width2Pixel (count) - 1, ypixel + font->ascent + 1); 2441 xpixel + Width2Pixel (count) - 1, ypixel + font->ascent + 1);
2391 } 2442 }
2392 } /* for (col....) */ 2443 } /* for (col....) */
2393 } /* for (row....) */ 2444 } /* for (row....) */
2394
2395#if ENABLE_OVERLAY
2396 scr_swap_overlay ();
2397#endif
2398 HOOK_INVOKE ((this, HOOK_REFRESH_END, DT_END));
2399 2445
2400 /* 2446 /*
2401 * G: cleanup cursor and display outline cursor if necessary 2447 * G: cleanup cursor and display outline cursor if necessary
2402 */ 2448 */
2403 if (showcursor) 2449 if (showcursor)
2435 2481
2436 XDrawRectangle (dpy, vt, gc, 2482 XDrawRectangle (dpy, vt, gc,
2437 Col2Pixel (col), 2483 Col2Pixel (col),
2438 Row2Pixel (oldcursor.row), 2484 Row2Pixel (oldcursor.row),
2439 (unsigned int) (Width2Pixel (cursorwidth) - 1), 2485 (unsigned int) (Width2Pixel (cursorwidth) - 1),
2440 (unsigned int) (Height2Pixel (1) - lineSpace - 1)); 2486 (unsigned int) (Height2Pixel (1) - 1));
2441 } 2487 }
2442 } 2488 }
2443 2489
2444 /* 2490 /*
2445 * H: cleanup selection 2491 * H: cleanup selection
2446 */ 2492 */
2493#if ENABLE_OVERLAY
2494 scr_swap_overlay ();
2495#endif
2496 HOOK_INVOKE ((this, HOOK_REFRESH_END, DT_END));
2497
2447 scr_reverse_selection (); 2498 scr_reverse_selection ();
2448 2499
2500 screen.flags = old_screen_flags;
2449 num_scr = 0; 2501 num_scr = 0;
2450 num_scr_allow = 1; 2502 num_scr_allow = 1;
2451} 2503}
2452 2504
2453void 2505void
2474 scr_remap_chars (swap_buf [i]); 2526 scr_remap_chars (swap_buf [i]);
2475 } 2527 }
2476} 2528}
2477 2529
2478void 2530void
2479rxvt_term::scr_recolour () NOTHROW 2531rxvt_term::scr_recolour (bool refresh) NOTHROW
2480{ 2532{
2533 bool transparent = false;
2534
2481#ifdef HAVE_BG_PIXMAP 2535#ifdef HAVE_BG_PIXMAP
2482 bgPixmap.apply (); 2536 if (bg_pixmap != None)
2483#else 2537 {
2538# ifdef ENABLE_TRANSPARENCY
2539 if (bg_flags & BG_IS_TRANSPARENT)
2540 {
2541 XSetWindowBackgroundPixmap (dpy, parent, bg_pixmap);
2542 XSetWindowBackgroundPixmap (dpy, vt, ParentRelative);
2484 2543
2544 transparent = true;
2545 }
2546 else
2547# endif
2548 {
2549 XSetWindowBackground (dpy, parent, pix_colors[Color_border]);
2550 XSetWindowBackgroundPixmap (dpy, vt, bg_pixmap);
2551 }
2552 }
2553 else
2554#endif
2555 {
2485 XSetWindowBackground (dpy, parent[0], pix_colors[Color_border]); 2556 XSetWindowBackground (dpy, parent, pix_colors[Color_border]);
2486 XClearWindow (dpy, parent[0]);
2487 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]); 2557 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
2558 }
2559
2560 XClearWindow (dpy, parent);
2488 2561
2489 if (scrollBar.win) 2562 if (scrollBar.win)
2490 { 2563 {
2564 if (transparent)
2565 XSetWindowBackgroundPixmap (dpy, scrollBar.win, ParentRelative);
2566 else
2491 XSetWindowBackground (dpy, scrollBar.win, pix_colors[Color_border]); 2567 XSetWindowBackground (dpy, scrollBar.win, pix_colors[Color_border]);
2492 scrollBar.state = STATE_IDLE; 2568 scrollBar.state = SB_STATE_IDLE;
2493 scrollBar.show (0); 2569 scrollBar.show (0);
2494 } 2570 }
2495 2571
2496#endif 2572 if (refresh)
2497 2573 {
2498 /* bgPixmap.apply () does not do the following : */
2499 scr_clear (); 2574 scr_clear ();
2500 scr_touch (true); 2575 scr_touch (true);
2576 }
2501 want_refresh = 1; 2577 want_refresh = 1;
2502} 2578}
2503 2579
2504/* ------------------------------------------------------------------------- */ 2580/* ------------------------------------------------------------------------- */
2505void 2581void
2573 { 2649 {
2574#if !ENABLE_MINIMAL 2650#if !ENABLE_MINIMAL
2575 if (selection.rect) 2651 if (selection.rect)
2576 scr_xor_rect (selection.beg.row, selection.beg.col, 2652 scr_xor_rect (selection.beg.row, selection.beg.col,
2577 selection.end.row, selection.end.col, 2653 selection.end.row, selection.end.col,
2578 RS_RVid, RS_RVid | RS_Uline); 2654 RS_Sel | RS_RVid, RS_Sel | RS_RVid | RS_Uline);
2579 else 2655 else
2580#endif 2656#endif
2581 scr_xor_span (selection.beg.row, selection.beg.col, 2657 scr_xor_span (selection.beg.row, selection.beg.col,
2582 selection.end.row, selection.end.col, 2658 selection.end.row, selection.end.col,
2583 RS_RVid); 2659 RS_Sel | RS_RVid);
2584 } 2660 }
2585} 2661}
2586 2662
2587/* ------------------------------------------------------------------------- */ 2663/* ------------------------------------------------------------------------- */
2588/* 2664/*
2591 */ 2667 */
2592#if 0 2668#if 0
2593void 2669void
2594rxvt_term::scr_dump (int fd) NOTHROW 2670rxvt_term::scr_dump (int fd) NOTHROW
2595{ 2671{
2596 int row, wrote; 2672 // if this method is needed, it can be implemented by factoring the
2597 unsigned int width, towrite; 2673 // relevant code in scr_printscreen
2598 char r1[] = "\n";
2599
2600 for (row = saveLines + top_row;
2601 row < saveLines + nrow - 1; row++)
2602 {
2603 width = row_buf[row].l >= 0 ? row_buf[row].l
2604 : ncol;
2605 for (towrite = width; towrite; towrite -= wrote)
2606 {
2607 wrote = write (fd, & (row_buf[row].t[width - towrite]),
2608 towrite);
2609 if (wrote < 0)
2610 return; /* XXX: death, no report */
2611 }
2612 if (row_buf[row].l >= 0)
2613 if (write (fd, r1, 1) <= 0)
2614 return; /* XXX: death, no report */
2615 }
2616} 2674}
2617#endif 2675#endif
2618 2676
2619/* ------------------------------------------------------------------------- * 2677/* ------------------------------------------------------------------------- *
2620 * CHARACTER SELECTION * 2678 * CHARACTER SELECTION *
2621 * ------------------------------------------------------------------------- */ 2679 * ------------------------------------------------------------------------- */
2622void 2680void
2623rxvt_term::selection_check (int check_more) NOTHROW 2681rxvt_term::selection_check (int check_more) NOTHROW
2624{ 2682{
2625 row_col_t pos;
2626
2627 if (!selection.op) 2683 if (!selection.op)
2628 return; 2684 return;
2629 2685
2630 pos.row = pos.col = 0;
2631 if (!IN_RANGE_EXC (selection.beg.row, top_row, nrow) 2686 if (!IN_RANGE_EXC (selection.beg.row, top_row, nrow)
2632 || !IN_RANGE_EXC (selection.mark.row, top_row, nrow) 2687 || !IN_RANGE_EXC (selection.mark.row, top_row, nrow)
2633 || !IN_RANGE_EXC (selection.end.row, top_row, nrow) 2688 || !IN_RANGE_EXC (selection.end.row, top_row, nrow)
2634 || (check_more == 1 2689 || (check_more == 1
2635 && current_screen == selection.screen 2690 && current_screen == selection.screen
2636 && !ROWCOL_IS_BEFORE (screen.cur, selection.beg) 2691 && !ROWCOL_IS_BEFORE (screen.cur, selection.beg)
2637 && ROWCOL_IS_BEFORE (screen.cur, selection.end)) 2692 && ROWCOL_IS_BEFORE (screen.cur, selection.end)))
2638 || (check_more == 2
2639 && ROWCOL_IS_BEFORE (selection.beg, pos)
2640 && ROWCOL_IS_AFTER (selection.end, pos))
2641 || (check_more == 3
2642 && ROWCOL_IS_AFTER (selection.end, pos))
2643 || (check_more == 4 /* screen width change */
2644 && (selection.beg.row != selection.end.row
2645 || selection.end.col > ncol)))
2646 CLEAR_SELECTION (); 2693 CLEAR_ALL_SELECTION ();
2647} 2694}
2648 2695
2649/* ------------------------------------------------------------------------- */ 2696/* ------------------------------------------------------------------------- */
2650/* 2697/*
2651 * Paste a selection direct to the command fd 2698 * Paste a selection direct to the command fd
2652 */ 2699 */
2653void 2700void
2654rxvt_term::paste (char *data, unsigned int len) NOTHROW 2701rxvt_term::tt_paste (char *data, unsigned int len) NOTHROW
2655{ 2702{
2656 /* convert normal newline chars into common keyboard Return key sequence */ 2703 /* convert normal newline chars into common keyboard Return key sequence */
2657 for (unsigned int i = 0; i < len; i++) 2704 for (unsigned int i = 0; i < len; i++)
2658 if (data[i] == C0_LF) 2705 if (data[i] == C0_LF)
2659 data[i] = C0_CR; 2706 data[i] = C0_CR;
2660 2707
2661 if (priv_modes & PrivMode_BracketPaste) 2708 if (priv_modes & PrivMode_BracketPaste)
2662 tt_printf ("\e[200~"); 2709 tt_printf ("\x1b[200~");
2663 2710
2664 tt_write (data, len); 2711 tt_write (data, len);
2665 2712
2666 if (priv_modes & PrivMode_BracketPaste) 2713 if (priv_modes & PrivMode_BracketPaste)
2667 tt_printf ("\e[201~"); 2714 tt_printf ("\x1b[201~");
2668} 2715}
2669 2716
2670/* ------------------------------------------------------------------------- */
2671/*
2672 * Respond to a notification that a primary selection has been sent
2673 * EXT: SelectionNotify
2674 */
2675void 2717void
2676rxvt_term::selection_paste (Window win, Atom prop, bool delete_prop) NOTHROW 2718rxvt_term::paste (char *data, unsigned int len) NOTHROW
2677{ 2719{
2678 if (prop == None) /* check for failed XConvertSelection */ 2720 if (HOOK_INVOKE ((this, HOOK_TT_PASTE, DT_STR_LEN, data, len, DT_END)))
2679 {
2680 if ((selection_type & Sel_CompoundText))
2681 {
2682 int selnum = selection_type & Sel_whereMask;
2683
2684 selection_type = 0;
2685 if (selnum != Sel_direct)
2686 selection_request_other (XA_STRING, selnum);
2687 }
2688
2689 if ((selection_type & Sel_UTF8String))
2690 {
2691 int selnum = selection_type & Sel_whereMask;
2692
2693 selection_type = Sel_CompoundText;
2694 if (selnum != Sel_direct)
2695 selection_request_other (xa[XA_COMPOUND_TEXT], selnum);
2696 else
2697 selection_type = 0;
2698 }
2699
2700 return;
2701 }
2702
2703 unsigned long bytes_after;
2704 XTextProperty ct;
2705
2706 if (XGetWindowProperty (dpy, win, prop,
2707 0, PROP_SIZE / 4,
2708 delete_prop, AnyPropertyType,
2709 &ct.encoding, &ct.format,
2710 &ct.nitems, &bytes_after,
2711 &ct.value) != Success)
2712 {
2713 ct.value = 0;
2714 goto bailout;
2715 }
2716
2717 if (ct.encoding == None)
2718 goto bailout;
2719
2720 if (bytes_after)
2721 {
2722 // fetch and append remaining data
2723 XTextProperty ct2;
2724
2725 if (XGetWindowProperty (dpy, win, prop,
2726 ct.nitems / 4, (bytes_after + 3) / 4,
2727 delete_prop, AnyPropertyType,
2728 &ct2.encoding, &ct2.format,
2729 &ct2.nitems, &bytes_after,
2730 &ct2.value) != Success)
2731 goto bailout;
2732
2733 // realloc should be compatible to XFree, here, and elsewhere, too
2734 ct.value = (unsigned char *)realloc (ct.value, ct.nitems + ct2.nitems + 1);
2735 memcpy (ct.value + ct.nitems, ct2.value, ct2.nitems + 1);
2736 ct.nitems += ct2.nitems;
2737
2738 XFree (ct2.value);
2739 }
2740
2741 if (ct.value == 0)
2742 goto bailout;
2743
2744 if (ct.encoding == xa[XA_INCR])
2745 {
2746 // INCR selection, start handshake
2747 if (!delete_prop)
2748 XDeleteProperty (dpy, win, prop);
2749
2750 selection_wait = Sel_incr;
2751 incr_buf_fill = 0;
2752 incr_ev.start (10);
2753
2754 goto bailout;
2755 }
2756
2757 if (ct.nitems == 0)
2758 {
2759 if (selection_wait == Sel_incr)
2760 {
2761 XFree (ct.value);
2762
2763 // finally complete, now paste the whole thing
2764 selection_wait = Sel_normal;
2765 ct.value = (unsigned char *)incr_buf;
2766 ct.nitems = incr_buf_fill;
2767 incr_buf = 0;
2768 incr_buf_size = 0;
2769 incr_ev.stop ();
2770 }
2771 else
2772 {
2773 if (selection_wait == Sel_normal
2774 && (win != display->root || prop != XA_CUT_BUFFER0)) // avoid recursion
2775 {
2776 /*
2777 * pass through again trying CUT_BUFFER0 if we've come from
2778 * XConvertSelection () but nothing was presented
2779 */
2780 selection_paste (display->root, XA_CUT_BUFFER0, False);
2781 }
2782
2783 goto bailout;
2784 }
2785 }
2786 else if (selection_wait == Sel_incr)
2787 {
2788 incr_ev.start (10);
2789
2790 while (incr_buf_fill + ct.nitems > incr_buf_size)
2791 {
2792 incr_buf_size = incr_buf_size ? incr_buf_size * 2 : 128*1024;
2793 incr_buf = (char *)realloc (incr_buf, incr_buf_size);
2794 }
2795
2796 memcpy (incr_buf + incr_buf_fill, ct.value, ct.nitems);
2797 incr_buf_fill += ct.nitems;
2798
2799 goto bailout;
2800 }
2801
2802 char **cl;
2803 int cr;
2804
2805#if !ENABLE_MINIMAL
2806 // xlib is horribly broken with respect to UTF8_STRING, and nobody cares to fix it
2807 // so recode it manually
2808 if (ct.encoding == xa[XA_UTF8_STRING])
2809 {
2810 wchar_t *w = rxvt_utf8towcs ((const char *)ct.value, ct.nitems);
2811 char *s = rxvt_wcstombs (w);
2812 free (w);
2813 // TODO: strlen == only the first element will be converted. well...
2814 paste (s, strlen (s));
2815 free (s);
2816 }
2817 else
2818#endif
2819 if (XmbTextPropertyToTextList (dpy, &ct, &cl, &cr) >= 0
2820 && cl)
2821 {
2822 for (int i = 0; i < cr; i++)
2823 paste (cl[i], strlen (cl[i]));
2824
2825 XFreeStringList (cl);
2826 }
2827 else
2828 paste ((char *)ct.value, ct.nitems); // paste raw
2829
2830bailout:
2831 XFree (ct.value);
2832
2833 if (selection_wait == Sel_normal)
2834 selection_wait = Sel_none;
2835}
2836
2837void
2838rxvt_term::incr_cb (ev::timer &w, int revents) NOTHROW
2839{
2840 selection_wait = Sel_none;
2841
2842 incr_buf_size = 0;
2843 free (incr_buf);
2844
2845 rxvt_warn ("data loss: timeout on INCR selection paste, ignoring.\n");
2846}
2847
2848void
2849rxvt_term::selection_property (Window win, Atom prop) NOTHROW
2850{
2851 if (prop == None || selection_wait != Sel_incr)
2852 return; 2721 return;
2853 2722
2854 selection_paste (win, prop, true); 2723 tt_paste (data, len);
2855} 2724}
2856 2725
2857/* ------------------------------------------------------------------------- */ 2726/* ------------------------------------------------------------------------- */
2858/* 2727/*
2859 * Request the current selection: 2728 * Request PRIMARY, SECONDARY or CLIPBOARD selection.
2860 * Order: > internal selection if available 2729 * if the requested selection has no owner or is empty CUT_BUFFER0 is used
2861 * > PRIMARY, SECONDARY, CLIPBOARD if ownership is claimed (+) 2730 * as fallback
2862 * > CUT_BUFFER0
2863 * (+) if ownership is claimed but property is empty, rxvt_selection_paste ()
2864 * will auto fallback to CUT_BUFFER0
2865 * EXT: button 2 release 2731 * EXT: button 2 release
2866 */ 2732 */
2867void 2733void
2868rxvt_term::selection_request (Time tm, int selnum) NOTHROW 2734rxvt_term::selection_request (Time tm, int selnum) NOTHROW
2869{ 2735{
2870 if (selection.text && selnum == Sel_Primary) 2736 if (!selection_req)
2871 {
2872 /* internal selection */
2873 char *str = rxvt_wcstombs (selection.text, selection.len);
2874 paste (str, strlen (str));
2875 free (str);
2876 return;
2877 } 2737 {
2878 else 2738 selection_req = new rxvt_selection (display, selnum, tm, vt, xa[XA_VT_SELECTION], this);
2739 selection_req->run ();
2879 { 2740 }
2880 selection_request_time = tm;
2881 selection_wait = Sel_normal;
2882
2883#if X_HAVE_UTF8_STRING
2884 selection_type = Sel_UTF8String;
2885 if (selection_request_other (xa[XA_UTF8_STRING], selnum))
2886 return;
2887#else
2888 selection_type = Sel_CompoundText;
2889 if (selection_request_other (xa[XA_COMPOUND_TEXT], selnum))
2890 return;
2891#endif
2892 }
2893
2894 selection_wait = Sel_none; /* don't loop in selection_paste () */
2895 selection_paste (display->root, XA_CUT_BUFFER0, false);
2896}
2897
2898int
2899rxvt_term::selection_request_other (Atom target, int selnum) NOTHROW
2900{
2901 Atom sel;
2902
2903 selection_type |= selnum;
2904
2905 if (selnum == Sel_Primary)
2906 sel = XA_PRIMARY;
2907 else if (selnum == Sel_Secondary)
2908 sel = XA_SECONDARY;
2909 else
2910 sel = xa[XA_CLIPBOARD];
2911
2912 if (XGetSelectionOwner (dpy, sel) != None)
2913 {
2914 XConvertSelection (dpy, sel, target, xa[XA_VT_SELECTION],
2915 vt, selection_request_time);
2916 return 1;
2917 }
2918
2919 return 0;
2920} 2741}
2921 2742
2922/* ------------------------------------------------------------------------- */ 2743/* ------------------------------------------------------------------------- */
2923/* 2744/*
2924 * Clear all selected text 2745 * Clear all selected text
2925 * EXT: SelectionClear 2746 * EXT: SelectionClear
2926 */ 2747 */
2927void 2748void
2928rxvt_term::selection_clear () NOTHROW 2749rxvt_term::selection_clear (bool clipboard) NOTHROW
2929{ 2750{
2751 if (!clipboard)
2752 {
2930 want_refresh = 1; 2753 want_refresh = 1;
2931 free (selection.text); 2754 free (selection.text);
2932 selection.text = NULL; 2755 selection.text = NULL;
2933 selection.len = 0; 2756 selection.len = 0;
2934 CLEAR_SELECTION (); 2757 CLEAR_SELECTION ();
2935 2758
2936 if (display->selection_owner == this) 2759 if (display->selection_owner == this)
2937 display->selection_owner = 0; 2760 display->selection_owner = 0;
2761 }
2762 else
2763 {
2764 free (selection.clip_text);
2765 selection.clip_text = NULL;
2766 selection.clip_len = 0;
2767
2768 if (display->clipboard_owner == this)
2769 display->clipboard_owner = 0;
2770 }
2938} 2771}
2939 2772
2940/* ------------------------------------------------------------------------- */ 2773/* ------------------------------------------------------------------------- */
2941/* 2774/*
2942 * Copy a selection into the cut buffer 2775 * Copy a selection into the cut buffer
2943 * EXT: button 1 or 3 release 2776 * EXT: button 1 or 3 release
2944 */ 2777 */
2945void 2778void
2946rxvt_term::selection_make (Time tm) 2779rxvt_term::selection_make (Time tm)
2947{ 2780{
2948 int i; 2781 int size;
2949 wchar_t *new_selection_text; 2782 wchar_t *new_selection_text;
2950 text_t *t; 2783 text_t *t;
2951 2784
2952 switch (selection.op) 2785 switch (selection.op)
2953 { 2786 {
2969 return; /* nothing selected, go away */ 2802 return; /* nothing selected, go away */
2970 2803
2971 if (HOOK_INVOKE ((this, HOOK_SEL_MAKE, DT_LONG, (long)tm, DT_END))) 2804 if (HOOK_INVOKE ((this, HOOK_SEL_MAKE, DT_LONG, (long)tm, DT_END)))
2972 return; 2805 return;
2973 2806
2974 i = (selection.end.row - selection.beg.row + 1) * (ncol + 1); 2807 size = (selection.end.row - selection.beg.row + 1) * (ncol + 1);
2975 new_selection_text = (wchar_t *)rxvt_malloc ((i + 4) * sizeof (wchar_t)); 2808 new_selection_text = (wchar_t *)rxvt_malloc ((size + 4) * sizeof (wchar_t));
2976 2809
2977 int ofs = 0; 2810 int ofs = 0;
2978 int extra = 0; 2811 int extra = 0;
2979 2812
2980 int col = selection.beg.col; 2813 int col = selection.beg.col;
2986 { 2819 {
2987#if !ENABLE_MINIMAL 2820#if !ENABLE_MINIMAL
2988 if (selection.rect) 2821 if (selection.rect)
2989 { 2822 {
2990 col = selection.beg.col; 2823 col = selection.beg.col;
2991 end_col = ncol + 1; 2824 end_col = selection.end.col;
2992 } 2825 }
2993 else 2826 else
2994#endif 2827#endif
2995 end_col = ROW(row).l; 2828 end_col = ROW(row).l;
2996 2829
2997 col = max (col, 0); 2830 col = max (col, 0);
2998 2831
2999 if (row == selection.end.row 2832 if (row == selection.end.row)
3000#if !ENABLE_MINIMAL
3001 || selection.rect
3002#endif
3003 )
3004 min_it (end_col, selection.end.col); 2833 min_it (end_col, selection.end.col);
3005 2834
3006 t = ROW(row).t + col; 2835 t = ROW(row).t + col;
3007 2836
3008 for (; col < end_col; col++) 2837 for (; col < end_col; col++)
3016 2845
3017 extra -= (len - 1); 2846 extra -= (len - 1);
3018 2847
3019 if (extra < 0) 2848 if (extra < 0)
3020 { 2849 {
3021 extra += i; 2850 extra += size;
3022 i += i; 2851 size += size;
3023 new_selection_text = (wchar_t *)rxvt_realloc (new_selection_text, (i + 4) * sizeof (wchar_t)); 2852 new_selection_text = (wchar_t *)rxvt_realloc (new_selection_text, (size + 4) * sizeof (wchar_t));
3024 } 2853 }
3025 2854
3026 ofs += rxvt_composite.expand (*t++, new_selection_text + ofs); 2855 ofs += rxvt_composite.expand (*t++, new_selection_text + ofs);
3027 } 2856 }
3028#endif 2857#endif
3040 2869
3041 new_selection_text[ofs++] = C0_LF; 2870 new_selection_text[ofs++] = C0_LF;
3042 } 2871 }
3043 else 2872 else
3044#endif 2873#endif
3045 if (!ROW(row).is_longer () && row != selection.end.row) 2874 if (!ROW(row).is_longer ()
2875 && (row != selection.end.row || end_col != selection.end.col)
2876 && (row != selection.beg.row || selection.beg.col < ncol))
3046 new_selection_text[ofs++] = C0_LF; 2877 new_selection_text[ofs++] = C0_LF;
3047 } 2878 }
3048
3049 if (end_col != selection.end.col)
3050 new_selection_text[ofs++] = C0_LF;
3051 2879
3052 new_selection_text[ofs] = 0; 2880 new_selection_text[ofs] = 0;
3053 2881
3054 if (ofs == 0) 2882 if (ofs == 0)
3055 { 2883 {
3068 2896
3069 selection_grab (tm); 2897 selection_grab (tm);
3070} 2898}
3071 2899
3072bool 2900bool
3073rxvt_term::selection_grab (Time tm) NOTHROW 2901rxvt_term::selection_grab (Time tm, bool clipboard) NOTHROW
3074{ 2902{
2903 Atom sel;
2904
2905 if (!clipboard)
2906 {
3075 selection_time = tm; 2907 selection_time = tm;
2908 sel = XA_PRIMARY;
2909 }
2910 else
2911 {
2912 clipboard_time = tm;
2913 sel = xa[XA_CLIPBOARD];
2914 }
3076 2915
3077 XSetSelectionOwner (dpy, XA_PRIMARY, vt, tm); 2916 XSetSelectionOwner (dpy, sel, vt, tm);
3078 if (XGetSelectionOwner (dpy, XA_PRIMARY) == vt) 2917 if (XGetSelectionOwner (dpy, sel) == vt)
3079 { 2918 {
3080 display->set_selection_owner (this); 2919 display->set_selection_owner (this, clipboard);
3081 return true; 2920 return true;
3082 } 2921 }
3083 else 2922 else
3084 { 2923 {
3085 selection_clear (); 2924 selection_clear (clipboard);
3086 return false; 2925 return false;
3087 } 2926 }
3088 2927
3089#if 0 2928#if 0
3090 XTextProperty ct; 2929 XTextProperty ct;
3550 * EXT: SelectionRequest 3389 * EXT: SelectionRequest
3551 */ 3390 */
3552void 3391void
3553rxvt_term::selection_send (const XSelectionRequestEvent &rq) NOTHROW 3392rxvt_term::selection_send (const XSelectionRequestEvent &rq) NOTHROW
3554{ 3393{
3394 Atom property = rq.property == None ? rq.target : rq.property;
3555 XSelectionEvent ev; 3395 XSelectionEvent ev;
3556 3396
3557 ev.type = SelectionNotify; 3397 ev.type = SelectionNotify;
3558 ev.property = None; 3398 ev.property = None;
3559 ev.display = rq.display; 3399 ev.display = rq.display;
3574 *target++ = xa[XA_COMPOUND_TEXT]; 3414 *target++ = xa[XA_COMPOUND_TEXT];
3575#if X_HAVE_UTF8_STRING 3415#if X_HAVE_UTF8_STRING
3576 *target++ = xa[XA_UTF8_STRING]; 3416 *target++ = xa[XA_UTF8_STRING];
3577#endif 3417#endif
3578 3418
3579 XChangeProperty (dpy, rq.requestor, rq.property, XA_ATOM, 3419 XChangeProperty (dpy, rq.requestor, property, XA_ATOM,
3580 32, PropModeReplace, 3420 32, PropModeReplace,
3581 (unsigned char *)target_list, target - target_list); 3421 (unsigned char *)target_list, target - target_list);
3582 ev.property = rq.property; 3422 ev.property = property;
3583 } 3423 }
3584#if TODO // TODO 3424#if TODO // TODO
3585 else if (rq.target == xa[XA_MULTIPLE]) 3425 else if (rq.target == xa[XA_MULTIPLE])
3586 { 3426 {
3587 /* TODO: Handle MULTIPLE */ 3427 /* TODO: Handle MULTIPLE */
3588 } 3428 }
3589#endif 3429#endif
3590 else if (rq.target == xa[XA_TIMESTAMP] && selection.text) 3430 else if (rq.target == xa[XA_TIMESTAMP] && rq.selection == XA_PRIMARY && selection.text)
3591 { 3431 {
3592 XChangeProperty (dpy, rq.requestor, rq.property, rq.target, 3432 XChangeProperty (dpy, rq.requestor, property, rq.target,
3593 32, PropModeReplace, (unsigned char *)&selection_time, 1); 3433 32, PropModeReplace, (unsigned char *)&selection_time, 1);
3594 ev.property = rq.property; 3434 ev.property = property;
3435 }
3436 else if (rq.target == xa[XA_TIMESTAMP] && rq.selection == xa[XA_CLIPBOARD] && selection.clip_text)
3437 {
3438 XChangeProperty (dpy, rq.requestor, property, rq.target,
3439 32, PropModeReplace, (unsigned char *)&clipboard_time, 1);
3440 ev.property = property;
3595 } 3441 }
3596 else if (rq.target == XA_STRING 3442 else if (rq.target == XA_STRING
3597 || rq.target == xa[XA_TEXT] 3443 || rq.target == xa[XA_TEXT]
3598 || rq.target == xa[XA_COMPOUND_TEXT] 3444 || rq.target == xa[XA_COMPOUND_TEXT]
3599 || rq.target == xa[XA_UTF8_STRING] 3445 || rq.target == xa[XA_UTF8_STRING]
3631 { 3477 {
3632 target = xa[XA_COMPOUND_TEXT]; 3478 target = xa[XA_COMPOUND_TEXT];
3633 style = enc_compound_text; 3479 style = enc_compound_text;
3634 } 3480 }
3635 3481
3636 if (selection.text) 3482 if (rq.selection == XA_PRIMARY && selection.text)
3637 { 3483 {
3638 cl = selection.text; 3484 cl = selection.text;
3639 selectlen = selection.len; 3485 selectlen = selection.len;
3486 }
3487 else if (rq.selection == xa[XA_CLIPBOARD] && selection.clip_text)
3488 {
3489 cl = selection.clip_text;
3490 selectlen = selection.clip_len;
3640 } 3491 }
3641 else 3492 else
3642 { 3493 {
3643 cl = L""; 3494 cl = L"";
3644 selectlen = 0; 3495 selectlen = 0;
3665 ct.value = (unsigned char *)cl; 3516 ct.value = (unsigned char *)cl;
3666 ct.nitems = selectlen; 3517 ct.nitems = selectlen;
3667 ct.encoding = target; 3518 ct.encoding = target;
3668 } 3519 }
3669 3520
3670 XChangeProperty (dpy, rq.requestor, rq.property, 3521 XChangeProperty (dpy, rq.requestor, property,
3671 ct.encoding, 8, PropModeReplace, 3522 ct.encoding, 8, PropModeReplace,
3672 ct.value, (int)ct.nitems); 3523 ct.value, (int)ct.nitems);
3673 ev.property = rq.property; 3524 ev.property = property;
3674 3525
3675 if (freect) 3526 if (freect)
3676 XFree (ct.value); 3527 XFree (ct.value);
3677 } 3528 }
3678 3529
3712 h += 2; min_it (h, nrow); 3563 h += 2; min_it (h, nrow);
3713 3564
3714 x -= 1; clamp_it (x, 0, ncol - w); 3565 x -= 1; clamp_it (x, 0, ncol - w);
3715 y -= 1; clamp_it (y, 0, nrow - h); 3566 y -= 1; clamp_it (y, 0, nrow - h);
3716 3567
3717 ov_x = x; ov_y = y; 3568 ov.x = x; ov.y = y;
3718 ov_w = w; ov_h = h; 3569 ov.w = w; ov.h = h;
3719 3570
3720 ov_text = new text_t *[h]; 3571 ov.text = new text_t *[h];
3721 ov_rend = new rend_t *[h]; 3572 ov.rend = new rend_t *[h];
3722 3573
3723 for (y = 0; y < h; y++) 3574 for (y = 0; y < h; y++)
3724 { 3575 {
3725 text_t *tp = ov_text[y] = new text_t[w]; 3576 text_t *tp = ov.text[y] = new text_t[w];
3726 rend_t *rp = ov_rend[y] = new rend_t[w]; 3577 rend_t *rp = ov.rend[y] = new rend_t[w];
3727 3578
3728 text_t t0, t1, t2; 3579 text_t t0, t1, t2;
3729 rend_t r = OVERLAY_RSTYLE; 3580 rend_t r = OVERLAY_RSTYLE;
3730 3581
3731 if (y == 0) 3582 if (y == 0)
3750} 3601}
3751 3602
3752void 3603void
3753rxvt_term::scr_overlay_off () NOTHROW 3604rxvt_term::scr_overlay_off () NOTHROW
3754{ 3605{
3755 if (!ov_text) 3606 if (!ov.text)
3756 return; 3607 return;
3757 3608
3758 want_refresh = 1; 3609 want_refresh = 1;
3759 3610
3760 for (int y = 0; y < ov_h; y++) 3611 for (int y = 0; y < ov.h; y++)
3761 { 3612 {
3762 delete [] ov_text[y]; 3613 delete [] ov.text[y];
3763 delete [] ov_rend[y]; 3614 delete [] ov.rend[y];
3764 } 3615 }
3765 3616
3766 delete [] ov_text; ov_text = 0; 3617 delete [] ov.text; ov.text = 0;
3767 delete [] ov_rend; ov_rend = 0; 3618 delete [] ov.rend; ov.rend = 0;
3768} 3619}
3769 3620
3770void 3621void
3771rxvt_term::scr_overlay_set (int x, int y, text_t text, rend_t rend) NOTHROW 3622rxvt_term::scr_overlay_set (int x, int y, text_t text, rend_t rend) NOTHROW
3772{ 3623{
3773 if (!ov_text || x >= ov_w - 2 || y >= ov_h - 2) 3624 if (!ov.text || x >= ov.w - 2 || y >= ov.h - 2)
3774 return; 3625 return;
3775 3626
3776 x++, y++; 3627 x++, y++;
3777 3628
3778 ov_text[y][x] = text; 3629 ov.text[y][x] = text;
3779 ov_rend[y][x] = rend; 3630 ov.rend[y][x] = rend;
3780} 3631}
3781 3632
3782void 3633void
3783rxvt_term::scr_overlay_set (int x, int y, const char *s) NOTHROW 3634rxvt_term::scr_overlay_set (int x, int y, const char *s) NOTHROW
3784{ 3635{
3803} 3654}
3804 3655
3805void 3656void
3806rxvt_term::scr_swap_overlay () NOTHROW 3657rxvt_term::scr_swap_overlay () NOTHROW
3807{ 3658{
3808 if (!ov_text) 3659 if (!ov.text)
3809 return; 3660 return;
3810 3661
3662 // hide cursor if it is within the overlay area
3663 if (IN_RANGE_EXC (screen.cur.col - ov.x, 0, ov.w)
3664 && IN_RANGE_EXC (screen.cur.row - ov.y, 0, ov.h))
3665 screen.flags &= ~Screen_VisibleCursor;
3666
3811 // swap screen mem with overlay 3667 // swap screen mem with overlay
3812 for (int y = ov_h; y--; ) 3668 for (int y = ov.h; y--; )
3813 { 3669 {
3814 text_t *t1 = ov_text[y]; 3670 text_t *t1 = ov.text[y];
3815 rend_t *r1 = ov_rend[y]; 3671 rend_t *r1 = ov.rend[y];
3816 3672
3817 text_t *t2 = ROW(y + ov_y + view_start).t + ov_x; 3673 text_t *t2 = ROW(y + ov.y + view_start).t + ov.x;
3818 rend_t *r2 = ROW(y + ov_y + view_start).r + ov_x; 3674 rend_t *r2 = ROW(y + ov.y + view_start).r + ov.x;
3819 3675
3820 for (int x = ov_w; x--; ) 3676 for (int x = ov.w; x--; )
3821 { 3677 {
3822 text_t t = *t1; *t1++ = *t2; *t2++ = t; 3678 text_t t = *t1; *t1++ = *t2; *t2++ = t;
3823 rend_t r = *r1; *r1++ = *r2; *r2++ = SET_FONT (r, FONTSET (r)->find_font (t)); 3679 rend_t r = *r1; *r1++ = *r2; *r2++ = SET_FONT (r, FONTSET (r)->find_font (t));
3824 } 3680 }
3825 } 3681 }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines