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.365 by sf-exg, Thu Jan 27 17:37:19 2011 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.
38 while (len--) 38 while (len--)
39 *start++ = value; 39 *start++ = value;
40} 40}
41 41
42/* ------------------------------------------------------------------------- */ 42/* ------------------------------------------------------------------------- */
43#define PROP_SIZE 256*1024
44#define PASTE_SIZE 32768
45#define TABSIZE 8 /* default tab size */ 43#define TABSIZE 8 /* default tab size */
46 44
47/* ------------------------------------------------------------------------- * 45/* ------------------------------------------------------------------------- *
48 * GENERAL SCREEN AND SELECTION UPDATE ROUTINES * 46 * GENERAL SCREEN AND SELECTION UPDATE ROUTINES *
49 * ------------------------------------------------------------------------- */ 47 * ------------------------------------------------------------------------- */
161 * ------------------------------------------------------------------------- */ 159 * ------------------------------------------------------------------------- */
162 160
163void 161void
164rxvt_term::scr_reset () 162rxvt_term::scr_reset ()
165{ 163{
164#if ENABLE_OVERLAY
165 scr_overlay_off ();
166#endif
167
166 view_start = 0; 168 view_start = 0;
167 num_scr = 0; 169 num_scr = 0;
168 170
169 if (ncol == 0) 171 if (ncol == 0)
170 ncol = 80; 172 ncol = 80;
201 term_start = 0; 203 term_start = 0;
202 204
203 talloc = new rxvt_salloc (ncol * sizeof (text_t)); 205 talloc = new rxvt_salloc (ncol * sizeof (text_t));
204 ralloc = new rxvt_salloc (ncol * sizeof (rend_t)); 206 ralloc = new rxvt_salloc (ncol * sizeof (rend_t));
205 207
206 row_buf = (line_t *)rxvt_calloc (total_rows + nrow, sizeof (line_t)); 208 row_buf = (line_t *)rxvt_calloc (total_rows , sizeof (line_t));
207 drawn_buf = (line_t *)rxvt_calloc (nrow , sizeof (line_t)); 209 drawn_buf = (line_t *)rxvt_calloc (nrow , sizeof (line_t));
208 swap_buf = (line_t *)rxvt_calloc (nrow , sizeof (line_t)); 210 swap_buf = (line_t *)rxvt_calloc (nrow , sizeof (line_t));
209 211
210 for (int row = nrow; row--; ) 212 for (int row = nrow; row--; )
211 { 213 {
273 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);
274 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);
275 } 277 }
276 278
277 line_t *old_buf = row_buf; 279 line_t *old_buf = row_buf;
278 row_buf = (line_t *)rxvt_calloc (total_rows + nrow, sizeof (line_t)); 280 row_buf = (line_t *)rxvt_calloc (total_rows, sizeof (line_t));
279 281
280 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
281 int pend = MOD (term_start + top_row , prev_total_rows); 283 int pend = MOD (term_start + top_row , prev_total_rows);
282 int q = total_rows; // rewrapped row 284 int q = total_rows; // rewrapped row
283 285
453 scr_clear (true); 455 scr_clear (true);
454 scr_refresh (); 456 scr_refresh ();
455} 457}
456 458
457void 459void
458rxvt_term::scr_soft_reset () 460rxvt_term::scr_soft_reset () NOTHROW
459{ 461{
460 /* only affects modes, nothing drastic such as clearing the screen */ 462 /* only affects modes, nothing drastic such as clearing the screen */
461#if ENABLE_OVERLAY 463#if ENABLE_OVERLAY
462 scr_overlay_off (); 464 scr_overlay_off ();
463#endif 465#endif
518 assert (s->cur.row >= 0); 520 assert (s->cur.row >= 0);
519 assert (s->cur.col >= 0); 521 assert (s->cur.col >= 0);
520} 522}
521 523
522void 524void
523rxvt_term::scr_swap_screen () 525rxvt_term::scr_swap_screen () NOTHROW
524{ 526{
525 if (!option (Opt_secondaryScreen)) 527 if (!option (Opt_secondaryScreen))
526 return; 528 return;
527 529
528 for (int i = prev_nrow; i--; ) 530 for (int i = prev_nrow; i--; )
547 return; 549 return;
548 550
549 want_refresh = 1; 551 want_refresh = 1;
550 view_start = 0; 552 view_start = 0;
551 553
552 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 ();
553 560
554 current_screen = scrn; 561 current_screen = scrn;
555 562
556#if NSCREENS 563#if NSCREENS
557 if (option (Opt_secondaryScreen)) 564 if (option (Opt_secondaryScreen))
636 643
637 if (count > 0 644 if (count > 0
638 && row1 == 0 645 && row1 == 0
639 && (current_screen == PRIMARY || option (Opt_secondaryScroll))) 646 && (current_screen == PRIMARY || option (Opt_secondaryScroll)))
640 { 647 {
648 min_it (count, total_rows - (nrow - (row2 + 1)));
649
641 top_row = max (top_row - count, -saveLines); 650 top_row = max (top_row - count, -saveLines);
642
643 // scroll everything up 'count' lines
644 term_start = (term_start + count) % total_rows;
645 651
646 // sever bottommost line 652 // sever bottommost line
647 { 653 {
648 line_t &l = ROW(row2 - count); 654 line_t &l = ROW(row2);
649 l.is_longer (0); 655 l.is_longer (0);
650 l.touch (); 656 l.touch ();
651 } 657 }
652 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
653 // erase newly scrolled-in lines 674 // erase newly scrolled-in lines
654 for (int i = count; i--; ) 675 for (int i = count; i--; )
655 { 676 {
656 line_t &l = ROW(nrow - 1 - i); 677 line_t &l = ROW(row2 - i);
657 678
658 // optimize if already cleared, can be significant on slow machines 679 // optimise if already cleared, can be significant on slow machines
659 // could be rolled into scr_blank_screen_mem 680 // could be rolled into scr_blank_screen_mem
660 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)))
661 { 682 {
662 scr_blank_line (l, 0, l.l, rstyle); 683 scr_blank_line (l, 0, l.l, rstyle);
663 l.l = 0; 684 l.l = 0;
665 } 686 }
666 else 687 else
667 scr_blank_screen_mem (l, rstyle); 688 scr_blank_screen_mem (l, rstyle);
668 } 689 }
669 690
670 // now copy lines below the scroll region bottom to the
671 // bottom of the screen again, so they look as if they
672 // hadn't moved.
673 for (int i = nrow; --i > row2; )
674 {
675 line_t &l1 = ROW(i - count);
676 line_t &l2 = ROW(i);
677
678 ::swap (l1, l2);
679 l2.touch ();
680 }
681
682 // move and/or clear selection, if any 691 // move and/or clear selection, if any
683 if (selection.op && current_screen == selection.screen) 692 if (selection.op && current_screen == selection.screen
693 && selection.beg.row <= row2)
684 { 694 {
685 selection.beg.row -= count; 695 selection.beg.row -= count;
686 selection.end.row -= count; 696 selection.end.row -= count;
687 selection.mark.row -= count; 697 selection.mark.row -= count;
688 698
689 if (selection.beg.row < top_row 699 selection_check (0);
690 || selection.end.row < top_row
691 || selection.mark.row < top_row)
692 {
693 CLEAR_ALL_SELECTION ();
694 selection.op = SELECTION_CLEAR;
695 }
696 } 700 }
697 701
698 // finally move the view window, if desired 702 // finally move the view window, if desired
699 if (option (Opt_scrollWithBuffer) 703 if (option (Opt_scrollWithBuffer)
700 && view_start != 0 704 && view_start != 0
730 } 734 }
731 735
732 // use a simple and robust scrolling algorithm, this 736 // use a simple and robust scrolling algorithm, this
733 // part of scr_scroll_text is not time-critical. 737 // part of scr_scroll_text is not time-critical.
734 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
735 int rows = row2 - row1 + 1; 747 int rows = row2 - row1 + 1;
736 748
737 min_it (count, rows); 749 min_it (count, rows);
738 750
739 line_t *temp_buf = row_buf + total_rows; 751 line_t *temp_buf = rxvt_temp_buf<line_t> (rows);
740 752
741 for (int row = 0; row < rows; row++) 753 for (int row = 0; row < rows; row++)
742 { 754 {
743 temp_buf [row] = ROW(row1 + (row + count + rows) % rows); 755 temp_buf [row] = ROW(row1 + (row + count + rows) % rows);
744 756
746 scr_blank_screen_mem (temp_buf [row], rstyle); 758 scr_blank_screen_mem (temp_buf [row], rstyle);
747 } 759 }
748 760
749 for (int row = 0; row < rows; row++) 761 for (int row = 0; row < rows; row++)
750 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 }
751 } 770 }
752 771
753 return count; 772 return count;
754} 773}
755 774
761rxvt_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
762{ 781{
763 if (len <= 0) /* sanity */ 782 if (len <= 0) /* sanity */
764 return; 783 return;
765 784
766 unsigned char checksel; 785 bool checksel;
767 unicode_t c; 786 unicode_t c;
768 int ncol = this->ncol; 787 int ncol = this->ncol;
769 const wchar_t *strend = str + len; 788 const wchar_t *strend = str + len;
770 789
771 want_refresh = 1; 790 want_refresh = 1;
797 816
798 while (str < strend) 817 while (str < strend)
799 { 818 {
800 c = (unicode_t)*str++; // convert to rxvt-unicodes representation 819 c = (unicode_t)*str++; // convert to rxvt-unicodes representation
801 820
802 if (expect_false (c < 0x20)) 821 if (ecb_unlikely (c < 0x20))
803 if (c == C0_LF) 822 if (c == C0_LF)
804 { 823 {
805 max_it (line->l, screen.cur.col); 824 max_it (line->l, screen.cur.col);
806 825
807 screen.flags &= ~Screen_WrapNext; 826 screen.flags &= ~Screen_WrapNext;
826 { 845 {
827 scr_tab (1, true); 846 scr_tab (1, true);
828 continue; 847 continue;
829 } 848 }
830 849
831 if (expect_false ( 850 if (ecb_unlikely (
832 checksel /* see if we're writing within selection */ 851 checksel /* see if we're writing within selection */
833 && !ROWCOL_IS_BEFORE (screen.cur, selection.beg) 852 && !ROWCOL_IS_BEFORE (screen.cur, selection.beg)
834 && ROWCOL_IS_BEFORE (screen.cur, selection.end) 853 && ROWCOL_IS_BEFORE (screen.cur, selection.end)
835 )) 854 ))
836 { 855 {
841 * should be a similar check. 860 * should be a similar check.
842 */ 861 */
843 CLEAR_SELECTION (); 862 CLEAR_SELECTION ();
844 } 863 }
845 864
846 if (expect_false (screen.flags & Screen_WrapNext)) 865 if (ecb_unlikely (screen.flags & Screen_WrapNext))
847 { 866 {
848 scr_do_wrap (); 867 scr_do_wrap ();
849 868
850 line->l = ncol; 869 line->l = ncol;
851 line->is_longer (1); 870 line->is_longer (1);
853 row = screen.cur.row; 872 row = screen.cur.row;
854 line = &ROW(row); /* _must_ refresh */ 873 line = &ROW(row); /* _must_ refresh */
855 } 874 }
856 875
857 // some utf-8 decoders "decode" surrogate characters: let's fix this. 876 // some utf-8 decoders "decode" surrogate characters: let's fix this.
858 if (expect_false (IN_RANGE_INC (c, 0xd800, 0xdfff))) 877 if (ecb_unlikely (IN_RANGE_INC (c, 0xd800, 0xdfff)))
859 c = 0xfffd; 878 c = 0xfffd;
860 879
861 // 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
862 // further replacements, as wcwidth might return -1 for the line 881 // further replacements, as wcwidth might return -1 for the line
863 // drawing characters below as they might be invalid in the current 882 // drawing characters below as they might be invalid in the current
864 // locale. 883 // locale.
865 int width = WCWIDTH (c); 884 int width = WCWIDTH (c);
866 885
867 if (expect_false (charsets [screen.charset] == '0')) // DEC SPECIAL 886 if (ecb_unlikely (charsets [screen.charset] == '0')) // DEC SPECIAL
868 { 887 {
869 // vt100 special graphics and line drawing 888 // vt100 special graphics and line drawing
870 // 5f-7e standard vt100 889 // 5f-7e standard vt100
871 // 40-5e rxvt extension for extra curses acs chars 890 // 40-5e rxvt extension for extra curses acs chars
872 static uint16_t vt100_0[62] = { // 41 .. 7e 891 static uint16_t vt100_0[62] = { // 41 .. 7e
885 c = vt100_0[c - 0x41]; 904 c = vt100_0[c - 0x41];
886 width = 1; // vt100 line drawing characters are always single-width 905 width = 1; // vt100 line drawing characters are always single-width
887 } 906 }
888 } 907 }
889 908
890 if (expect_false (screen.flags & Screen_Insert)) 909 if (ecb_unlikely (screen.flags & Screen_Insert))
891 scr_insdel_chars (width, INSERT); 910 scr_insdel_chars (width, INSERT);
892 911
893 if (width != 0) 912 if (width != 0)
894 { 913 {
895#if !UNICODE_3 914#if !UNICODE_3
903#endif 922#endif
904 923
905 rend_t rend = SET_FONT (rstyle, FONTSET (rstyle)->find_font (c)); 924 rend_t rend = SET_FONT (rstyle, FONTSET (rstyle)->find_font (c));
906 925
907 // if the character doesn't fit into the remaining columns... 926 // if the character doesn't fit into the remaining columns...
908 if (expect_false (screen.cur.col > ncol - width && ncol >= width)) 927 if (ecb_unlikely (screen.cur.col > ncol - width && ncol >= width))
909 { 928 {
910 if (screen.flags & Screen_Autowrap) 929 if (screen.flags & Screen_Autowrap)
911 { 930 {
912 // ... artificially enlargen the previous one 931 // ... artificially enlargen the previous one
913 c = NOCHAR; 932 c = NOCHAR;
920 939
921 // nuke the character at this position, if required 940 // nuke the character at this position, if required
922 // due to wonderful coincidences everywhere else in this loop 941 // due to wonderful coincidences everywhere else in this loop
923 // we never have to check for overwriting a wide char itself, 942 // we never have to check for overwriting a wide char itself,
924 // only its tail. 943 // only its tail.
925 if (expect_false (line->t[screen.cur.col] == NOCHAR)) 944 if (ecb_unlikely (line->t[screen.cur.col] == NOCHAR))
926 scr_kill_char (*line, screen.cur.col); 945 scr_kill_char (*line, screen.cur.col);
927 946
928 line->touch (); 947 line->touch ();
929 948
930 do 949 do
931 { 950 {
932 line->t[screen.cur.col] = c; 951 line->t[screen.cur.col] = c;
933 line->r[screen.cur.col] = rend; 952 line->r[screen.cur.col] = rend;
934 953
935 if (expect_true (screen.cur.col < ncol - 1)) 954 if (ecb_likely (screen.cur.col < ncol - 1))
936 screen.cur.col++; 955 screen.cur.col++;
937 else 956 else
938 { 957 {
939 line->l = ncol; 958 line->l = ncol;
940 if (screen.flags & Screen_Autowrap) 959 if (screen.flags & Screen_Autowrap)
943 goto end_of_line; 962 goto end_of_line;
944 } 963 }
945 964
946 c = NOCHAR; 965 c = NOCHAR;
947 } 966 }
948 while (expect_false (--width > 0)); 967 while (ecb_unlikely (--width > 0));
949 968
950 // pad with spaces when overwriting wide character with smaller one 969 // pad with spaces when overwriting wide character with smaller one
951 for (int c = screen.cur.col; expect_false (c < ncol && line->t[c] == NOCHAR); c++) 970 for (int c = screen.cur.col; ecb_unlikely (c < ncol && line->t[c] == NOCHAR); c++)
952 { 971 {
953 line->t[c] = ' '; 972 line->t[c] = ' ';
954 line->r[c] = rend; 973 line->r[c] = rend;
955 } 974 }
956 975
1293 scr_blank_line (line, col, num, rstyle); 1312 scr_blank_line (line, col, num, rstyle);
1294} 1313}
1295 1314
1296/* ------------------------------------------------------------------------- */ 1315/* ------------------------------------------------------------------------- */
1297/* 1316/*
1298 * Erase part of whole of the screen 1317 * Erase part or whole of the screen
1299 * XTERM_SEQ: Clear screen after cursor : ESC [ 0 J 1318 * XTERM_SEQ: Clear screen after cursor : ESC [ 0 J
1300 * XTERM_SEQ: Clear screen before cursor: ESC [ 1 J 1319 * XTERM_SEQ: Clear screen before cursor: ESC [ 1 J
1301 * XTERM_SEQ: Clear whole screen : ESC [ 2 J 1320 * XTERM_SEQ: Clear whole screen : ESC [ 2 J
1302 */ 1321 */
1303void 1322void
1312 ZERO_SCROLLBACK (); 1331 ZERO_SCROLLBACK ();
1313 1332
1314 switch (mode) 1333 switch (mode)
1315 { 1334 {
1316 case 0: /* erase to end of screen */ 1335 case 0: /* erase to end of screen */
1317 selection_check (1);
1318 scr_erase_line (0); 1336 scr_erase_line (0);
1319 row = screen.cur.row + 1; /* possible OOB */ 1337 row = screen.cur.row + 1; /* possible OOB */
1320 num = nrow - row; 1338 num = nrow - row;
1321 break; 1339 break;
1322 case 1: /* erase to beginning of screen */ 1340 case 1: /* erase to beginning of screen */
1323 selection_check (3);
1324 scr_erase_line (1); 1341 scr_erase_line (1);
1325 row = 0; 1342 row = 0;
1326 num = screen.cur.row; 1343 num = screen.cur.row;
1327 break; 1344 break;
1328 case 2: /* erase whole screen */ 1345 case 2: /* erase whole screen */
1329 selection_check (3);
1330 row = 0; 1346 row = 0;
1331 num = nrow; 1347 num = nrow;
1332 break; 1348 break;
1333 default: 1349 default:
1334 return; 1350 return;
1351 { 1367 {
1352 ren = DEFAULT_RSTYLE; 1368 ren = DEFAULT_RSTYLE;
1353 1369
1354 if (mapped) 1370 if (mapped)
1355 XClearArea (dpy, vt, 0, 1371 XClearArea (dpy, vt, 0,
1356 Row2Pixel (row - view_start), (unsigned int)width, 1372 Row2Pixel (row - view_start), (unsigned int)vt_width,
1357 (unsigned int)Height2Pixel (num), False); 1373 (unsigned int)Height2Pixel (num), False);
1358 } 1374 }
1359 else 1375 else
1360 { 1376 {
1361 ren = rstyle & (RS_fgMask | RS_bgMask); 1377 ren = rstyle & (RS_fgMask | RS_bgMask);
1364 { 1380 {
1365 gcvalue.foreground = pix_colors[bgcolor_of (rstyle)]; 1381 gcvalue.foreground = pix_colors[bgcolor_of (rstyle)];
1366 XChangeGC (dpy, gc, GCForeground, &gcvalue); 1382 XChangeGC (dpy, gc, GCForeground, &gcvalue);
1367 XFillRectangle (dpy, vt, gc, 1383 XFillRectangle (dpy, vt, gc,
1368 0, Row2Pixel (row - view_start), 1384 0, Row2Pixel (row - view_start),
1369 (unsigned int)width, 1385 (unsigned int)vt_width,
1370 (unsigned int)Height2Pixel (num)); 1386 (unsigned int)Height2Pixel (num));
1371 gcvalue.foreground = pix_colors[Color_fg]; 1387 gcvalue.foreground = pix_colors[Color_fg];
1372 XChangeGC (dpy, gc, GCForeground, &gcvalue); 1388 XChangeGC (dpy, gc, GCForeground, &gcvalue);
1373 } 1389 }
1374 } 1390 }
1405 1421
1406 want_refresh = 1; 1422 want_refresh = 1;
1407 ZERO_SCROLLBACK (); 1423 ZERO_SCROLLBACK ();
1408 1424
1409 num_scr_allow = 0; 1425 num_scr_allow = 0;
1410 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 ();
1411 1431
1412 fs = SET_FONT (rstyle, FONTSET (rstyle)->find_font ('E')); 1432 fs = SET_FONT (rstyle, FONTSET (rstyle)->find_font ('E'));
1413 for (int row = nrow; row--; ) 1433 for (int row = nrow; row--; )
1414 { 1434 {
1415 line_t &line = ROW(row); 1435 line_t &line = ROW(row);
1856 * Refresh the entire screen 1876 * Refresh the entire screen
1857 */ 1877 */
1858void 1878void
1859rxvt_term::scr_touch (bool refresh) NOTHROW 1879rxvt_term::scr_touch (bool refresh) NOTHROW
1860{ 1880{
1861 scr_expose (0, 0, width, height, refresh); 1881 scr_expose (0, 0, vt_width, vt_height, refresh);
1862} 1882}
1863 1883
1864/* ------------------------------------------------------------------------- */ 1884/* ------------------------------------------------------------------------- */
1865/* 1885/*
1866 * 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
1922 1942
1923# ifndef NO_MAPALERT 1943# ifndef NO_MAPALERT
1924# ifdef MAPALERT_OPTION 1944# ifdef MAPALERT_OPTION
1925 if (option (Opt_mapAlert)) 1945 if (option (Opt_mapAlert))
1926# endif 1946# endif
1927 XMapWindow (dpy, parent[0]); 1947 XMapWindow (dpy, parent);
1928# endif 1948# endif
1929 1949
1930# if ENABLE_FRILLS 1950# if ENABLE_FRILLS
1931 if (option (Opt_urgentOnBell)) 1951 if (option (Opt_urgentOnBell))
1932 set_urgency (1); 1952 set_urgency (1);
1945 HOOK_INVOKE ((this, HOOK_BELL, DT_END)); 1965 HOOK_INVOKE ((this, HOOK_BELL, DT_END));
1946#endif 1966#endif
1947} 1967}
1948 1968
1949/* ------------------------------------------------------------------------- */ 1969/* ------------------------------------------------------------------------- */
1950/* ARGSUSED */
1951void 1970void
1952rxvt_term::scr_printscreen (int fullhist) NOTHROW 1971rxvt_term::scr_printscreen (int fullhist) NOTHROW
1953{ 1972{
1954#ifdef PRINTPIPE 1973#ifdef PRINTPIPE
1955 int nrows, row_start; 1974 int nrows, row_start;
2029 * A: set up vars 2048 * A: set up vars
2030 */ 2049 */
2031 refresh_count = 0; 2050 refresh_count = 0;
2032 2051
2033 unsigned int old_screen_flags = screen.flags; 2052 unsigned int old_screen_flags = screen.flags;
2034 char have_bg = 0; 2053 bool have_bg = 0;
2035#ifdef HAVE_BG_PIXMAP 2054#ifdef HAVE_BG_PIXMAP
2036 have_bg = bg_pixmap != None; 2055 have_bg = bg_pixmap != None;
2037#endif 2056#endif
2038 ocrow = oldcursor.row; /* is there an old outline cursor on screen? */ 2057 ocrow = oldcursor.row; /* is there an old outline cursor on screen? */
2039 2058
2045 HOOK_INVOKE ((this, HOOK_REFRESH_BEGIN, DT_END)); 2064 HOOK_INVOKE ((this, HOOK_REFRESH_BEGIN, DT_END));
2046#if ENABLE_OVERLAY 2065#if ENABLE_OVERLAY
2047 scr_swap_overlay (); 2066 scr_swap_overlay ();
2048#endif 2067#endif
2049 2068
2050 char showcursor = screen.flags & Screen_VisibleCursor; 2069 bool showcursor = screen.flags & Screen_VisibleCursor;
2051 2070
2052 /* 2071 /*
2053 * C: set the cursor character (s) 2072 * C: set the cursor character (s)
2054 */ 2073 */
2055 { 2074 {
2056 unsigned char setoldcursor; 2075 bool setoldcursor;
2057 2076
2058#ifdef CURSOR_BLINK 2077#ifdef CURSOR_BLINK
2059 if (hidden_cursor) 2078 if (hidden_cursor)
2060 showcursor = 0; 2079 showcursor = 0;
2061#endif 2080#endif
2148 { 2167 {
2149 int16_t nits; 2168 int16_t nits;
2150 int i = num_scr; 2169 int i = num_scr;
2151 int j; 2170 int j;
2152 int len, wlen; 2171 int len, wlen;
2153 dLocal (int, num_scr);
2154 2172
2155 j = nrow; 2173 j = nrow;
2156 wlen = len = -1; 2174 wlen = len = -1;
2157 row = i > 0 ? 0 : j - 1; 2175 row = i > 0 ? 0 : j - 1;
2158 2176
2233 continue; 2251 continue;
2234 2252
2235 // redraw one or more characters 2253 // redraw one or more characters
2236 2254
2237 // seek to the beginning of wide characters 2255 // seek to the beginning of wide characters
2238 while (expect_false (stp[col] == NOCHAR && col > 0)) 2256 while (ecb_unlikely (stp[col] == NOCHAR && col > 0))
2239 --col; 2257 --col;
2240 2258
2241 rend_t rend = srp[col]; /* screen rendition (target rendition) */ 2259 rend_t rend = srp[col]; /* screen rendition (target rendition) */
2242 text_t *text = stp + col; 2260 text_t *text = stp + col;
2243 int count = 1; 2261 int count = 1;
2281 2299
2282 col--; /* went one too far. move back */ 2300 col--; /* went one too far. move back */
2283 count -= i; /* dump any matching trailing chars */ 2301 count -= i; /* dump any matching trailing chars */
2284 2302
2285 // sometimes we optimize away the trailing NOCHAR's, add them back 2303 // sometimes we optimize away the trailing NOCHAR's, add them back
2286 while (expect_false (i && text[count] == NOCHAR)) 2304 while (ecb_unlikely (i && text[count] == NOCHAR))
2287 count++, i--; 2305 count++, i--;
2288 2306
2289 /* 2307 /*
2290 * Determine the attributes for the string 2308 * Determine the attributes for the string
2291 */ 2309 */
2292 int fore = fgcolor_of (rend); // desired foreground 2310 int fore = fgcolor_of (rend); // desired foreground
2293 int back = bgcolor_of (rend); // desired background 2311 int back = bgcolor_of (rend); // desired background
2294 2312
2295 // 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
2296 if (expect_false (rend & (RS_baseattrMask | RS_Careful | RS_Sel))) 2314 if (ecb_unlikely (rend & (RS_baseattrMask | RS_Careful | RS_Sel)))
2297 { 2315 {
2298 bool invert = rend & RS_RVid; 2316 bool invert = rend & RS_RVid;
2299 2317
2300#ifndef NO_BOLD_UNDERLINE_REVERSE 2318#ifndef NO_BOLD_UNDERLINE_REVERSE
2301 if (rend & RS_Bold && fore == Color_fg) 2319 if (rend & RS_Bold && fore == Color_fg)
2390 /* 2408 /*
2391 * Actually do the drawing of the string here 2409 * Actually do the drawing of the string here
2392 */ 2410 */
2393 rxvt_font *font = (*fontset[GET_STYLE (rend)])[GET_FONT (rend)]; 2411 rxvt_font *font = (*fontset[GET_STYLE (rend)])[GET_FONT (rend)];
2394 2412
2395 if (expect_true (have_bg && back == Color_bg)) 2413 if (ecb_likely (have_bg && back == Color_bg))
2396 { 2414 {
2397 // this is very ugly, maybe push it into ->draw? 2415 // this is very ugly, maybe push it into ->draw?
2398 2416
2399 for (i = 0; i < count; i++) /* don't draw empty strings */ 2417 for (i = 0; i < count; i++) /* don't draw empty strings */
2400 if (text[i] != ' ') 2418 if (text[i] != ' ')
2407 did_clear: ; 2425 did_clear: ;
2408 } 2426 }
2409 else 2427 else
2410 font->draw (*drawable, xpixel, ypixel, text, count, fore, back); 2428 font->draw (*drawable, xpixel, ypixel, text, count, fore, back);
2411 2429
2412 if (expect_false (rend & RS_Uline && font->descent > 1 && fore != back)) 2430 if (ecb_unlikely (rend & RS_Uline && font->descent > 1 && fore != back))
2413 { 2431 {
2414#if ENABLE_FRILLS 2432#if ENABLE_FRILLS
2415 if (ISSET_PIXCOLOR (Color_underline)) 2433 if (ISSET_PIXCOLOR (Color_underline))
2416 XSetForeground (dpy, gc, pix_colors[Color_underline]); 2434 XSetForeground (dpy, gc, pix_colors[Color_underline]);
2417 else 2435 else
2463 2481
2464 XDrawRectangle (dpy, vt, gc, 2482 XDrawRectangle (dpy, vt, gc,
2465 Col2Pixel (col), 2483 Col2Pixel (col),
2466 Row2Pixel (oldcursor.row), 2484 Row2Pixel (oldcursor.row),
2467 (unsigned int) (Width2Pixel (cursorwidth) - 1), 2485 (unsigned int) (Width2Pixel (cursorwidth) - 1),
2468 (unsigned int) (Height2Pixel (1) - lineSpace - 1)); 2486 (unsigned int) (Height2Pixel (1) - 1));
2469 } 2487 }
2470 } 2488 }
2471 2489
2472 /* 2490 /*
2473 * H: cleanup selection 2491 * H: cleanup selection
2516 2534
2517#ifdef HAVE_BG_PIXMAP 2535#ifdef HAVE_BG_PIXMAP
2518 if (bg_pixmap != None) 2536 if (bg_pixmap != None)
2519 { 2537 {
2520# ifdef ENABLE_TRANSPARENCY 2538# ifdef ENABLE_TRANSPARENCY
2521 if (bg_flags & isTransparent) 2539 if (bg_flags & BG_IS_TRANSPARENT)
2522 { 2540 {
2523 XSetWindowBackgroundPixmap (dpy, parent[0], bg_pixmap); 2541 XSetWindowBackgroundPixmap (dpy, parent, bg_pixmap);
2524 XSetWindowBackgroundPixmap (dpy, vt, ParentRelative); 2542 XSetWindowBackgroundPixmap (dpy, vt, ParentRelative);
2525 2543
2526 transparent = true; 2544 transparent = true;
2527 } 2545 }
2528 else 2546 else
2529# endif 2547# endif
2530 { 2548 {
2531 XSetWindowBackground (dpy, parent[0], pix_colors[Color_border]); 2549 XSetWindowBackground (dpy, parent, pix_colors[Color_border]);
2532 XSetWindowBackgroundPixmap (dpy, vt, bg_pixmap); 2550 XSetWindowBackgroundPixmap (dpy, vt, bg_pixmap);
2533 } 2551 }
2534 } 2552 }
2535 else 2553 else
2536#endif 2554#endif
2537 { 2555 {
2538 XSetWindowBackground (dpy, parent[0], pix_colors[Color_border]); 2556 XSetWindowBackground (dpy, parent, pix_colors[Color_border]);
2539 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]); 2557 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
2540 } 2558 }
2541 2559
2542 XClearWindow (dpy, parent[0]); 2560 XClearWindow (dpy, parent);
2543 2561
2544 if (scrollBar.win) 2562 if (scrollBar.win)
2545 { 2563 {
2546 if (transparent) 2564 if (transparent)
2547 XSetWindowBackgroundPixmap (dpy, scrollBar.win, ParentRelative); 2565 XSetWindowBackgroundPixmap (dpy, scrollBar.win, ParentRelative);
2548 else 2566 else
2549 XSetWindowBackground (dpy, scrollBar.win, pix_colors[Color_border]); 2567 XSetWindowBackground (dpy, scrollBar.win, pix_colors[Color_border]);
2550 scrollBar.state = STATE_IDLE; 2568 scrollBar.state = SB_STATE_IDLE;
2551 scrollBar.show (0); 2569 scrollBar.show (0);
2552 } 2570 }
2553 2571
2554 if (refresh) 2572 if (refresh)
2555 { 2573 {
2649 */ 2667 */
2650#if 0 2668#if 0
2651void 2669void
2652rxvt_term::scr_dump (int fd) NOTHROW 2670rxvt_term::scr_dump (int fd) NOTHROW
2653{ 2671{
2654 int row, wrote; 2672 // if this method is needed, it can be implemented by factoring the
2655 unsigned int width, towrite; 2673 // relevant code in scr_printscreen
2656 const char r1[] = "\n";
2657
2658 for (row = saveLines + top_row;
2659 row < saveLines + nrow - 1; row++)
2660 {
2661 width = row_buf[row].l >= 0 ? row_buf[row].l
2662 : ncol;
2663 for (towrite = width; towrite; towrite -= wrote)
2664 {
2665 wrote = write (fd, & (row_buf[row].t[width - towrite]),
2666 towrite);
2667 if (wrote < 0)
2668 return; /* XXX: death, no report */
2669 }
2670 if (row_buf[row].l >= 0)
2671 if (write (fd, r1, 1) <= 0)
2672 return; /* XXX: death, no report */
2673 }
2674} 2674}
2675#endif 2675#endif
2676 2676
2677/* ------------------------------------------------------------------------- * 2677/* ------------------------------------------------------------------------- *
2678 * CHARACTER SELECTION * 2678 * CHARACTER SELECTION *
2679 * ------------------------------------------------------------------------- */ 2679 * ------------------------------------------------------------------------- */
2680void 2680void
2681rxvt_term::selection_check (int check_more) NOTHROW 2681rxvt_term::selection_check (int check_more) NOTHROW
2682{ 2682{
2683 row_col_t pos;
2684
2685 if (!selection.op) 2683 if (!selection.op)
2686 return; 2684 return;
2687 2685
2688 pos.row = pos.col = 0;
2689 if (!IN_RANGE_EXC (selection.beg.row, top_row, nrow) 2686 if (!IN_RANGE_EXC (selection.beg.row, top_row, nrow)
2690 || !IN_RANGE_EXC (selection.mark.row, top_row, nrow) 2687 || !IN_RANGE_EXC (selection.mark.row, top_row, nrow)
2691 || !IN_RANGE_EXC (selection.end.row, top_row, nrow) 2688 || !IN_RANGE_EXC (selection.end.row, top_row, nrow)
2692 || (check_more == 1 2689 || (check_more == 1
2693 && current_screen == selection.screen 2690 && current_screen == selection.screen
2694 && !ROWCOL_IS_BEFORE (screen.cur, selection.beg) 2691 && !ROWCOL_IS_BEFORE (screen.cur, selection.beg)
2695 && ROWCOL_IS_BEFORE (screen.cur, selection.end)) 2692 && ROWCOL_IS_BEFORE (screen.cur, selection.end)))
2696 || (check_more == 2
2697 && ROWCOL_IS_BEFORE (selection.beg, pos)
2698 && ROWCOL_IS_AFTER (selection.end, pos))
2699 || (check_more == 3
2700 && ROWCOL_IS_AFTER (selection.end, pos))
2701 || (check_more == 4 /* screen width change */
2702 && (selection.beg.row != selection.end.row
2703 || selection.end.col > ncol)))
2704 CLEAR_SELECTION (); 2693 CLEAR_ALL_SELECTION ();
2705} 2694}
2706 2695
2707/* ------------------------------------------------------------------------- */ 2696/* ------------------------------------------------------------------------- */
2708/* 2697/*
2709 * Paste a selection direct to the command fd 2698 * Paste a selection direct to the command fd
2715 for (unsigned int i = 0; i < len; i++) 2704 for (unsigned int i = 0; i < len; i++)
2716 if (data[i] == C0_LF) 2705 if (data[i] == C0_LF)
2717 data[i] = C0_CR; 2706 data[i] = C0_CR;
2718 2707
2719 if (priv_modes & PrivMode_BracketPaste) 2708 if (priv_modes & PrivMode_BracketPaste)
2720 tt_printf ("\e[200~"); 2709 tt_printf ("\x1b[200~");
2721 2710
2722 tt_write (data, len); 2711 tt_write (data, len);
2723 2712
2724 if (priv_modes & PrivMode_BracketPaste) 2713 if (priv_modes & PrivMode_BracketPaste)
2725 tt_printf ("\e[201~"); 2714 tt_printf ("\x1b[201~");
2726} 2715}
2727 2716
2728void 2717void
2729rxvt_term::paste (char *data, unsigned int len) NOTHROW 2718rxvt_term::paste (char *data, unsigned int len) NOTHROW
2730{ 2719{
2734 tt_paste (data, len); 2723 tt_paste (data, len);
2735} 2724}
2736 2725
2737/* ------------------------------------------------------------------------- */ 2726/* ------------------------------------------------------------------------- */
2738/* 2727/*
2739 * Respond to a notification that a primary selection has been sent 2728 * Request PRIMARY, SECONDARY or CLIPBOARD selection.
2740 * EXT: SelectionNotify 2729 * if the requested selection has no owner or is empty CUT_BUFFER0 is used
2741 */ 2730 * as fallback
2742void
2743rxvt_term::selection_paste (Window win, Atom prop, bool delete_prop) NOTHROW
2744{
2745 if (prop == None) /* check for failed XConvertSelection */
2746 {
2747 if ((selection_type & Sel_CompoundText))
2748 {
2749 int selnum = selection_type & Sel_whereMask;
2750
2751 selection_type = 0;
2752 if (selnum != Sel_direct)
2753 selection_request_other (XA_STRING, selnum);
2754 }
2755
2756 if ((selection_type & Sel_UTF8String))
2757 {
2758 int selnum = selection_type & Sel_whereMask;
2759
2760 selection_type = Sel_CompoundText;
2761 if (selnum != Sel_direct)
2762 selection_request_other (xa[XA_COMPOUND_TEXT], selnum);
2763 else
2764 selection_type = 0;
2765 }
2766
2767 return;
2768 }
2769
2770 unsigned long bytes_after;
2771 XTextProperty ct;
2772
2773 if (XGetWindowProperty (dpy, win, prop,
2774 0, PROP_SIZE / 4,
2775 delete_prop, AnyPropertyType,
2776 &ct.encoding, &ct.format,
2777 &ct.nitems, &bytes_after,
2778 &ct.value) != Success)
2779 {
2780 ct.value = 0;
2781 goto bailout;
2782 }
2783
2784 if (ct.encoding == None)
2785 goto bailout;
2786
2787 if (bytes_after)
2788 {
2789 // fetch and append remaining data
2790 XTextProperty ct2;
2791
2792 if (XGetWindowProperty (dpy, win, prop,
2793 ct.nitems / 4, (bytes_after + 3) / 4,
2794 delete_prop, AnyPropertyType,
2795 &ct2.encoding, &ct2.format,
2796 &ct2.nitems, &bytes_after,
2797 &ct2.value) != Success)
2798 goto bailout;
2799
2800 // realloc should be compatible to XFree, here, and elsewhere, too
2801 ct.value = (unsigned char *)rxvt_realloc (ct.value, ct.nitems + ct2.nitems + 1);
2802 memcpy (ct.value + ct.nitems, ct2.value, ct2.nitems + 1);
2803 ct.nitems += ct2.nitems;
2804
2805 XFree (ct2.value);
2806 }
2807
2808 if (ct.value == 0)
2809 goto bailout;
2810
2811 if (ct.encoding == xa[XA_INCR])
2812 {
2813 // INCR selection, start handshake
2814 if (!delete_prop)
2815 XDeleteProperty (dpy, win, prop);
2816
2817 selection_wait = Sel_incr;
2818 incr_buf_fill = 0;
2819 incr_ev.start (10);
2820
2821 goto bailout;
2822 }
2823
2824 if (ct.nitems == 0)
2825 {
2826 if (selection_wait == Sel_incr)
2827 {
2828 XFree (ct.value);
2829
2830 // finally complete, now paste the whole thing
2831 selection_wait = Sel_normal;
2832 ct.value = (unsigned char *)incr_buf;
2833 ct.nitems = incr_buf_fill;
2834 incr_buf = 0;
2835 incr_buf_size = 0;
2836 incr_ev.stop ();
2837 }
2838 else
2839 {
2840 if (selection_wait == Sel_normal
2841 && (win != display->root || prop != XA_CUT_BUFFER0)) // avoid recursion
2842 {
2843 /*
2844 * pass through again trying CUT_BUFFER0 if we've come from
2845 * XConvertSelection () but nothing was presented
2846 */
2847 selection_paste (display->root, XA_CUT_BUFFER0, False);
2848 }
2849
2850 goto bailout;
2851 }
2852 }
2853 else if (selection_wait == Sel_incr)
2854 {
2855 incr_ev.start (10);
2856
2857 while (incr_buf_fill + ct.nitems > incr_buf_size)
2858 {
2859 incr_buf_size = incr_buf_size ? incr_buf_size * 2 : 128*1024;
2860 incr_buf = (char *)rxvt_realloc (incr_buf, incr_buf_size);
2861 }
2862
2863 memcpy (incr_buf + incr_buf_fill, ct.value, ct.nitems);
2864 incr_buf_fill += ct.nitems;
2865
2866 goto bailout;
2867 }
2868
2869 char **cl;
2870 int cr;
2871
2872#if !ENABLE_MINIMAL
2873 // xlib is horribly broken with respect to UTF8_STRING, and nobody cares to fix it
2874 // so recode it manually
2875 if (ct.encoding == xa[XA_UTF8_STRING])
2876 {
2877 wchar_t *w = rxvt_utf8towcs ((const char *)ct.value, ct.nitems);
2878 char *s = rxvt_wcstombs (w);
2879 free (w);
2880 // TODO: strlen == only the first element will be converted. well...
2881 paste (s, strlen (s));
2882 free (s);
2883 }
2884 else
2885#endif
2886 if (XmbTextPropertyToTextList (dpy, &ct, &cl, &cr) >= 0
2887 && cl)
2888 {
2889 for (int i = 0; i < cr; i++)
2890 paste (cl[i], strlen (cl[i]));
2891
2892 XFreeStringList (cl);
2893 }
2894 else
2895 paste ((char *)ct.value, ct.nitems); // paste raw
2896
2897bailout:
2898 XFree (ct.value);
2899
2900 if (selection_wait == Sel_normal)
2901 selection_wait = Sel_none;
2902}
2903
2904void
2905rxvt_term::incr_cb (ev::timer &w, int revents) NOTHROW
2906{
2907 selection_wait = Sel_none;
2908
2909 incr_buf_size = 0;
2910 free (incr_buf);
2911
2912 rxvt_warn ("data loss: timeout on INCR selection paste, ignoring.\n");
2913}
2914
2915void
2916rxvt_term::selection_property (Window win, Atom prop) NOTHROW
2917{
2918 if (prop == None || selection_wait != Sel_incr)
2919 return;
2920
2921 selection_paste (win, prop, true);
2922}
2923
2924/* ------------------------------------------------------------------------- */
2925/*
2926 * Request the current selection:
2927 * Order: > internal selection if available
2928 * > PRIMARY, SECONDARY, CLIPBOARD if ownership is claimed (+)
2929 * > CUT_BUFFER0
2930 * (+) if ownership is claimed but property is empty, rxvt_selection_paste ()
2931 * will auto fallback to CUT_BUFFER0
2932 * EXT: button 2 release 2731 * EXT: button 2 release
2933 */ 2732 */
2934void 2733void
2935rxvt_term::selection_request (Time tm, int selnum) NOTHROW 2734rxvt_term::selection_request (Time tm, int selnum) NOTHROW
2936{ 2735{
2937 if (selection.text && selnum == Sel_Primary) 2736 if (!selection_req)
2938 {
2939 /* internal selection */
2940 char *str = rxvt_wcstombs (selection.text, selection.len);
2941 paste (str, strlen (str));
2942 free (str);
2943 return;
2944 } 2737 {
2945 else 2738 selection_req = new rxvt_selection (display, selnum, tm, vt, xa[XA_VT_SELECTION], this);
2739 selection_req->run ();
2946 { 2740 }
2947 selection_request_time = tm;
2948 selection_wait = Sel_normal;
2949
2950#if X_HAVE_UTF8_STRING
2951 selection_type = Sel_UTF8String;
2952 if (selection_request_other (xa[XA_UTF8_STRING], selnum))
2953 return;
2954#else
2955 selection_type = Sel_CompoundText;
2956 if (selection_request_other (xa[XA_COMPOUND_TEXT], selnum))
2957 return;
2958#endif
2959 }
2960
2961 selection_wait = Sel_none; /* don't loop in selection_paste () */
2962 selection_paste (display->root, XA_CUT_BUFFER0, false);
2963}
2964
2965int
2966rxvt_term::selection_request_other (Atom target, int selnum) NOTHROW
2967{
2968 Atom sel;
2969
2970 selection_type |= selnum;
2971
2972 if (selnum == Sel_Primary)
2973 sel = XA_PRIMARY;
2974 else if (selnum == Sel_Secondary)
2975 sel = XA_SECONDARY;
2976 else
2977 sel = xa[XA_CLIPBOARD];
2978
2979 if (XGetSelectionOwner (dpy, sel) != None)
2980 {
2981 XConvertSelection (dpy, sel, target, xa[XA_VT_SELECTION],
2982 vt, selection_request_time);
2983 return 1;
2984 }
2985
2986 return 0;
2987} 2741}
2988 2742
2989/* ------------------------------------------------------------------------- */ 2743/* ------------------------------------------------------------------------- */
2990/* 2744/*
2991 * Clear all selected text 2745 * Clear all selected text
3635 * EXT: SelectionRequest 3389 * EXT: SelectionRequest
3636 */ 3390 */
3637void 3391void
3638rxvt_term::selection_send (const XSelectionRequestEvent &rq) NOTHROW 3392rxvt_term::selection_send (const XSelectionRequestEvent &rq) NOTHROW
3639{ 3393{
3394 Atom property = rq.property == None ? rq.target : rq.property;
3640 XSelectionEvent ev; 3395 XSelectionEvent ev;
3641 3396
3642 ev.type = SelectionNotify; 3397 ev.type = SelectionNotify;
3643 ev.property = None; 3398 ev.property = None;
3644 ev.display = rq.display; 3399 ev.display = rq.display;
3659 *target++ = xa[XA_COMPOUND_TEXT]; 3414 *target++ = xa[XA_COMPOUND_TEXT];
3660#if X_HAVE_UTF8_STRING 3415#if X_HAVE_UTF8_STRING
3661 *target++ = xa[XA_UTF8_STRING]; 3416 *target++ = xa[XA_UTF8_STRING];
3662#endif 3417#endif
3663 3418
3664 XChangeProperty (dpy, rq.requestor, rq.property, XA_ATOM, 3419 XChangeProperty (dpy, rq.requestor, property, XA_ATOM,
3665 32, PropModeReplace, 3420 32, PropModeReplace,
3666 (unsigned char *)target_list, target - target_list); 3421 (unsigned char *)target_list, target - target_list);
3667 ev.property = rq.property; 3422 ev.property = property;
3668 } 3423 }
3669#if TODO // TODO 3424#if TODO // TODO
3670 else if (rq.target == xa[XA_MULTIPLE]) 3425 else if (rq.target == xa[XA_MULTIPLE])
3671 { 3426 {
3672 /* TODO: Handle MULTIPLE */ 3427 /* TODO: Handle MULTIPLE */
3673 } 3428 }
3674#endif 3429#endif
3675 else if (rq.target == xa[XA_TIMESTAMP] && rq.selection == XA_PRIMARY && selection.text) 3430 else if (rq.target == xa[XA_TIMESTAMP] && rq.selection == XA_PRIMARY && selection.text)
3676 { 3431 {
3677 XChangeProperty (dpy, rq.requestor, rq.property, rq.target, 3432 XChangeProperty (dpy, rq.requestor, property, rq.target,
3678 32, PropModeReplace, (unsigned char *)&selection_time, 1); 3433 32, PropModeReplace, (unsigned char *)&selection_time, 1);
3679 ev.property = rq.property; 3434 ev.property = property;
3680 } 3435 }
3681 else if (rq.target == xa[XA_TIMESTAMP] && rq.selection == xa[XA_CLIPBOARD] && selection.clip_text) 3436 else if (rq.target == xa[XA_TIMESTAMP] && rq.selection == xa[XA_CLIPBOARD] && selection.clip_text)
3682 { 3437 {
3683 XChangeProperty (dpy, rq.requestor, rq.property, rq.target, 3438 XChangeProperty (dpy, rq.requestor, property, rq.target,
3684 32, PropModeReplace, (unsigned char *)&clipboard_time, 1); 3439 32, PropModeReplace, (unsigned char *)&clipboard_time, 1);
3685 ev.property = rq.property; 3440 ev.property = property;
3686 } 3441 }
3687 else if (rq.target == XA_STRING 3442 else if (rq.target == XA_STRING
3688 || rq.target == xa[XA_TEXT] 3443 || rq.target == xa[XA_TEXT]
3689 || rq.target == xa[XA_COMPOUND_TEXT] 3444 || rq.target == xa[XA_COMPOUND_TEXT]
3690 || rq.target == xa[XA_UTF8_STRING] 3445 || rq.target == xa[XA_UTF8_STRING]
3761 ct.value = (unsigned char *)cl; 3516 ct.value = (unsigned char *)cl;
3762 ct.nitems = selectlen; 3517 ct.nitems = selectlen;
3763 ct.encoding = target; 3518 ct.encoding = target;
3764 } 3519 }
3765 3520
3766 XChangeProperty (dpy, rq.requestor, rq.property, 3521 XChangeProperty (dpy, rq.requestor, property,
3767 ct.encoding, 8, PropModeReplace, 3522 ct.encoding, 8, PropModeReplace,
3768 ct.value, (int)ct.nitems); 3523 ct.value, (int)ct.nitems);
3769 ev.property = rq.property; 3524 ev.property = property;
3770 3525
3771 if (freect) 3526 if (freect)
3772 XFree (ct.value); 3527 XFree (ct.value);
3773 } 3528 }
3774 3529

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines