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.352 by root, Fri Oct 15 20:52:15 2010 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
400 } 402 }
401 403
402 free (tabs); 404 free (tabs);
403 tabs = (char *)rxvt_malloc (ncol); 405 tabs = (char *)rxvt_malloc (ncol);
404 406
405 for (int col = ncol; --col; ) 407 for (int col = ncol; col--; )
406 tabs [col] = col % TABSIZE == 0; 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;
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;
917 else 936 else
918 screen.cur.col = ncol - width; 937 screen.cur.col = ncol - width;
919 } 938 }
920 939
921 // nuke the character at this position, if required 940 // nuke the character at this position, if required
922 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.
923 line->t[screen.cur.col] == NOCHAR 944 if (ecb_unlikely (line->t[screen.cur.col] == NOCHAR))
924 || (screen.cur.col < ncol - 1
925 && line->t[screen.cur.col + 1] == NOCHAR)
926 ))
927 scr_kill_char (*line, screen.cur.col); 945 scr_kill_char (*line, screen.cur.col);
928 946
929 line->touch (); 947 line->touch ();
930 948
931 do 949 do
932 { 950 {
933 line->t[screen.cur.col] = c; 951 line->t[screen.cur.col] = c;
934 line->r[screen.cur.col] = rend; 952 line->r[screen.cur.col] = rend;
935 953
936 if (expect_true (screen.cur.col < ncol - 1)) 954 if (ecb_likely (screen.cur.col < ncol - 1))
937 screen.cur.col++; 955 screen.cur.col++;
938 else 956 else
939 { 957 {
940 line->l = ncol; 958 line->l = ncol;
941 if (screen.flags & Screen_Autowrap) 959 if (screen.flags & Screen_Autowrap)
944 goto end_of_line; 962 goto end_of_line;
945 } 963 }
946 964
947 c = NOCHAR; 965 c = NOCHAR;
948 } 966 }
949 while (expect_false (--width > 0)); 967 while (ecb_unlikely (--width > 0));
950 968
951 // pad with spaces when overwriting wide character with smaller one 969 // pad with spaces when overwriting wide character with smaller one
952 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++)
953 { 971 {
954 line->t[c] = ' '; 972 line->t[c] = ' ';
955 line->r[c] = rend; 973 line->r[c] = rend;
956 } 974 }
957 975
1294 scr_blank_line (line, col, num, rstyle); 1312 scr_blank_line (line, col, num, rstyle);
1295} 1313}
1296 1314
1297/* ------------------------------------------------------------------------- */ 1315/* ------------------------------------------------------------------------- */
1298/* 1316/*
1299 * Erase part of whole of the screen 1317 * Erase part or whole of the screen
1300 * XTERM_SEQ: Clear screen after cursor : ESC [ 0 J 1318 * XTERM_SEQ: Clear screen after cursor : ESC [ 0 J
1301 * XTERM_SEQ: Clear screen before cursor: ESC [ 1 J 1319 * XTERM_SEQ: Clear screen before cursor: ESC [ 1 J
1302 * XTERM_SEQ: Clear whole screen : ESC [ 2 J 1320 * XTERM_SEQ: Clear whole screen : ESC [ 2 J
1303 */ 1321 */
1304void 1322void
1313 ZERO_SCROLLBACK (); 1331 ZERO_SCROLLBACK ();
1314 1332
1315 switch (mode) 1333 switch (mode)
1316 { 1334 {
1317 case 0: /* erase to end of screen */ 1335 case 0: /* erase to end of screen */
1318 selection_check (1);
1319 scr_erase_line (0); 1336 scr_erase_line (0);
1320 row = screen.cur.row + 1; /* possible OOB */ 1337 row = screen.cur.row + 1; /* possible OOB */
1321 num = nrow - row; 1338 num = nrow - row;
1322 break; 1339 break;
1323 case 1: /* erase to beginning of screen */ 1340 case 1: /* erase to beginning of screen */
1324 selection_check (3);
1325 scr_erase_line (1); 1341 scr_erase_line (1);
1326 row = 0; 1342 row = 0;
1327 num = screen.cur.row; 1343 num = screen.cur.row;
1328 break; 1344 break;
1329 case 2: /* erase whole screen */ 1345 case 2: /* erase whole screen */
1330 selection_check (3);
1331 row = 0; 1346 row = 0;
1332 num = nrow; 1347 num = nrow;
1333 break; 1348 break;
1334 default: 1349 default:
1335 return; 1350 return;
1352 { 1367 {
1353 ren = DEFAULT_RSTYLE; 1368 ren = DEFAULT_RSTYLE;
1354 1369
1355 if (mapped) 1370 if (mapped)
1356 XClearArea (dpy, vt, 0, 1371 XClearArea (dpy, vt, 0,
1357 Row2Pixel (row - view_start), (unsigned int)width, 1372 Row2Pixel (row - view_start), (unsigned int)vt_width,
1358 (unsigned int)Height2Pixel (num), False); 1373 (unsigned int)Height2Pixel (num), False);
1359 } 1374 }
1360 else 1375 else
1361 { 1376 {
1362 ren = rstyle & (RS_fgMask | RS_bgMask); 1377 ren = rstyle & (RS_fgMask | RS_bgMask);
1365 { 1380 {
1366 gcvalue.foreground = pix_colors[bgcolor_of (rstyle)]; 1381 gcvalue.foreground = pix_colors[bgcolor_of (rstyle)];
1367 XChangeGC (dpy, gc, GCForeground, &gcvalue); 1382 XChangeGC (dpy, gc, GCForeground, &gcvalue);
1368 XFillRectangle (dpy, vt, gc, 1383 XFillRectangle (dpy, vt, gc,
1369 0, Row2Pixel (row - view_start), 1384 0, Row2Pixel (row - view_start),
1370 (unsigned int)width, 1385 (unsigned int)vt_width,
1371 (unsigned int)Height2Pixel (num)); 1386 (unsigned int)Height2Pixel (num));
1372 gcvalue.foreground = pix_colors[Color_fg]; 1387 gcvalue.foreground = pix_colors[Color_fg];
1373 XChangeGC (dpy, gc, GCForeground, &gcvalue); 1388 XChangeGC (dpy, gc, GCForeground, &gcvalue);
1374 } 1389 }
1375 } 1390 }
1406 1421
1407 want_refresh = 1; 1422 want_refresh = 1;
1408 ZERO_SCROLLBACK (); 1423 ZERO_SCROLLBACK ();
1409 1424
1410 num_scr_allow = 0; 1425 num_scr_allow = 0;
1411 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 ();
1412 1431
1413 fs = SET_FONT (rstyle, FONTSET (rstyle)->find_font ('E')); 1432 fs = SET_FONT (rstyle, FONTSET (rstyle)->find_font ('E'));
1414 for (int row = nrow; row--; ) 1433 for (int row = nrow; row--; )
1415 { 1434 {
1416 line_t &line = ROW(row); 1435 line_t &line = ROW(row);
1686 { 1705 {
1687 rvideo_state = on; 1706 rvideo_state = on;
1688 1707
1689 ::swap (pix_colors[Color_fg], pix_colors[Color_bg]); 1708 ::swap (pix_colors[Color_fg], pix_colors[Color_bg]);
1690#ifdef HAVE_BG_PIXMAP 1709#ifdef HAVE_BG_PIXMAP
1691 if (bgPixmap.pixmap == None) 1710 if (bg_pixmap == None)
1692#endif 1711#endif
1693 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]); 1712 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
1694 1713
1695 XGCValues gcvalue; 1714 XGCValues gcvalue;
1696 gcvalue.foreground = pix_colors[Color_fg]; 1715 gcvalue.foreground = pix_colors[Color_fg];
1857 * Refresh the entire screen 1876 * Refresh the entire screen
1858 */ 1877 */
1859void 1878void
1860rxvt_term::scr_touch (bool refresh) NOTHROW 1879rxvt_term::scr_touch (bool refresh) NOTHROW
1861{ 1880{
1862 scr_expose (0, 0, width, height, refresh); 1881 scr_expose (0, 0, vt_width, vt_height, refresh);
1863} 1882}
1864 1883
1865/* ------------------------------------------------------------------------- */ 1884/* ------------------------------------------------------------------------- */
1866/* 1885/*
1867 * 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
1923 1942
1924# ifndef NO_MAPALERT 1943# ifndef NO_MAPALERT
1925# ifdef MAPALERT_OPTION 1944# ifdef MAPALERT_OPTION
1926 if (option (Opt_mapAlert)) 1945 if (option (Opt_mapAlert))
1927# endif 1946# endif
1928 XMapWindow (dpy, parent[0]); 1947 XMapWindow (dpy, parent);
1929# endif 1948# endif
1930 1949
1931# if ENABLE_FRILLS 1950# if ENABLE_FRILLS
1932 if (option (Opt_urgentOnBell)) 1951 if (option (Opt_urgentOnBell))
1933 set_urgency (1); 1952 set_urgency (1);
1946 HOOK_INVOKE ((this, HOOK_BELL, DT_END)); 1965 HOOK_INVOKE ((this, HOOK_BELL, DT_END));
1947#endif 1966#endif
1948} 1967}
1949 1968
1950/* ------------------------------------------------------------------------- */ 1969/* ------------------------------------------------------------------------- */
1951/* ARGSUSED */
1952void 1970void
1953rxvt_term::scr_printscreen (int fullhist) NOTHROW 1971rxvt_term::scr_printscreen (int fullhist) NOTHROW
1954{ 1972{
1955#ifdef PRINTPIPE 1973#ifdef PRINTPIPE
1956 int nrows, row_start; 1974 int nrows, row_start;
2030 * A: set up vars 2048 * A: set up vars
2031 */ 2049 */
2032 refresh_count = 0; 2050 refresh_count = 0;
2033 2051
2034 unsigned int old_screen_flags = screen.flags; 2052 unsigned int old_screen_flags = screen.flags;
2035 char have_bg = 0; 2053 bool have_bg = 0;
2036#ifdef HAVE_BG_PIXMAP 2054#ifdef HAVE_BG_PIXMAP
2037 have_bg = bgPixmap.pixmap != None; 2055 have_bg = bg_pixmap != None;
2038#endif 2056#endif
2039 ocrow = oldcursor.row; /* is there an old outline cursor on screen? */ 2057 ocrow = oldcursor.row; /* is there an old outline cursor on screen? */
2040 2058
2041 /* 2059 /*
2042 * B: reverse any characters which are selected 2060 * B: reverse any characters which are selected
2046 HOOK_INVOKE ((this, HOOK_REFRESH_BEGIN, DT_END)); 2064 HOOK_INVOKE ((this, HOOK_REFRESH_BEGIN, DT_END));
2047#if ENABLE_OVERLAY 2065#if ENABLE_OVERLAY
2048 scr_swap_overlay (); 2066 scr_swap_overlay ();
2049#endif 2067#endif
2050 2068
2051 char showcursor = screen.flags & Screen_VisibleCursor; 2069 bool showcursor = screen.flags & Screen_VisibleCursor;
2052 2070
2053 /* 2071 /*
2054 * C: set the cursor character (s) 2072 * C: set the cursor character (s)
2055 */ 2073 */
2056 { 2074 {
2057 unsigned char setoldcursor; 2075 bool setoldcursor;
2058 2076
2059#ifdef CURSOR_BLINK 2077#ifdef CURSOR_BLINK
2060 if (hidden_cursor) 2078 if (hidden_cursor)
2061 showcursor = 0; 2079 showcursor = 0;
2062#endif 2080#endif
2149 { 2167 {
2150 int16_t nits; 2168 int16_t nits;
2151 int i = num_scr; 2169 int i = num_scr;
2152 int j; 2170 int j;
2153 int len, wlen; 2171 int len, wlen;
2154 dLocal (int, num_scr);
2155 2172
2156 j = nrow; 2173 j = nrow;
2157 wlen = len = -1; 2174 wlen = len = -1;
2158 row = i > 0 ? 0 : j - 1; 2175 row = i > 0 ? 0 : j - 1;
2159 2176
2234 continue; 2251 continue;
2235 2252
2236 // redraw one or more characters 2253 // redraw one or more characters
2237 2254
2238 // seek to the beginning of wide characters 2255 // seek to the beginning of wide characters
2239 while (expect_false (stp[col] == NOCHAR && col > 0)) 2256 while (ecb_unlikely (stp[col] == NOCHAR && col > 0))
2240 --col; 2257 --col;
2241 2258
2242 rend_t rend = srp[col]; /* screen rendition (target rendition) */ 2259 rend_t rend = srp[col]; /* screen rendition (target rendition) */
2243 text_t *text = stp + col; 2260 text_t *text = stp + col;
2244 int count = 1; 2261 int count = 1;
2282 2299
2283 col--; /* went one too far. move back */ 2300 col--; /* went one too far. move back */
2284 count -= i; /* dump any matching trailing chars */ 2301 count -= i; /* dump any matching trailing chars */
2285 2302
2286 // sometimes we optimize away the trailing NOCHAR's, add them back 2303 // sometimes we optimize away the trailing NOCHAR's, add them back
2287 while (expect_false (i && text[count] == NOCHAR)) 2304 while (ecb_unlikely (i && text[count] == NOCHAR))
2288 count++, i--; 2305 count++, i--;
2289 2306
2290 /* 2307 /*
2291 * Determine the attributes for the string 2308 * Determine the attributes for the string
2292 */ 2309 */
2293 int fore = fgcolor_of (rend); // desired foreground 2310 int fore = fgcolor_of (rend); // desired foreground
2294 int back = bgcolor_of (rend); // desired background 2311 int back = bgcolor_of (rend); // desired background
2295 2312
2296 // 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
2297 if (expect_false (rend & (RS_baseattrMask | RS_Careful | RS_Sel))) 2314 if (ecb_unlikely (rend & (RS_baseattrMask | RS_Careful | RS_Sel)))
2298 { 2315 {
2299 bool invert = rend & RS_RVid; 2316 bool invert = rend & RS_RVid;
2300 2317
2301#ifndef NO_BOLD_UNDERLINE_REVERSE 2318#ifndef NO_BOLD_UNDERLINE_REVERSE
2302 if (rend & RS_Bold && fore == Color_fg) 2319 if (rend & RS_Bold && fore == Color_fg)
2391 /* 2408 /*
2392 * Actually do the drawing of the string here 2409 * Actually do the drawing of the string here
2393 */ 2410 */
2394 rxvt_font *font = (*fontset[GET_STYLE (rend)])[GET_FONT (rend)]; 2411 rxvt_font *font = (*fontset[GET_STYLE (rend)])[GET_FONT (rend)];
2395 2412
2396 if (expect_true (have_bg && back == Color_bg)) 2413 if (ecb_likely (have_bg && back == Color_bg))
2397 { 2414 {
2398 // this is very ugly, maybe push it into ->draw? 2415 // this is very ugly, maybe push it into ->draw?
2399 2416
2400 for (i = 0; i < count; i++) /* don't draw empty strings */ 2417 for (i = 0; i < count; i++) /* don't draw empty strings */
2401 if (text[i] != ' ') 2418 if (text[i] != ' ')
2408 did_clear: ; 2425 did_clear: ;
2409 } 2426 }
2410 else 2427 else
2411 font->draw (*drawable, xpixel, ypixel, text, count, fore, back); 2428 font->draw (*drawable, xpixel, ypixel, text, count, fore, back);
2412 2429
2413 if (expect_false (rend & RS_Uline && font->descent > 1 && fore != back)) 2430 if (ecb_unlikely (rend & RS_Uline && font->descent > 1 && fore != back))
2414 { 2431 {
2415#if ENABLE_FRILLS 2432#if ENABLE_FRILLS
2416 if (ISSET_PIXCOLOR (Color_underline)) 2433 if (ISSET_PIXCOLOR (Color_underline))
2417 XSetForeground (dpy, gc, pix_colors[Color_underline]); 2434 XSetForeground (dpy, gc, pix_colors[Color_underline]);
2418 else 2435 else
2464 2481
2465 XDrawRectangle (dpy, vt, gc, 2482 XDrawRectangle (dpy, vt, gc,
2466 Col2Pixel (col), 2483 Col2Pixel (col),
2467 Row2Pixel (oldcursor.row), 2484 Row2Pixel (oldcursor.row),
2468 (unsigned int) (Width2Pixel (cursorwidth) - 1), 2485 (unsigned int) (Width2Pixel (cursorwidth) - 1),
2469 (unsigned int) (Height2Pixel (1) - lineSpace - 1)); 2486 (unsigned int) (Height2Pixel (1) - 1));
2470 } 2487 }
2471 } 2488 }
2472 2489
2473 /* 2490 /*
2474 * H: cleanup selection 2491 * H: cleanup selection
2509 scr_remap_chars (swap_buf [i]); 2526 scr_remap_chars (swap_buf [i]);
2510 } 2527 }
2511} 2528}
2512 2529
2513void 2530void
2514rxvt_term::scr_recolour () NOTHROW 2531rxvt_term::scr_recolour (bool refresh) NOTHROW
2515{ 2532{
2533 bool transparent = false;
2534
2516#ifdef HAVE_BG_PIXMAP 2535#ifdef HAVE_BG_PIXMAP
2517 bgPixmap.apply (); 2536 if (bg_pixmap != None)
2518#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);
2519 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 {
2520 XSetWindowBackground (dpy, parent[0], pix_colors[Color_border]); 2556 XSetWindowBackground (dpy, parent, pix_colors[Color_border]);
2521 XClearWindow (dpy, parent[0]);
2522 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]); 2557 XSetWindowBackground (dpy, vt, pix_colors[Color_bg]);
2558 }
2559
2560 XClearWindow (dpy, parent);
2523 2561
2524 if (scrollBar.win) 2562 if (scrollBar.win)
2525 { 2563 {
2564 if (transparent)
2565 XSetWindowBackgroundPixmap (dpy, scrollBar.win, ParentRelative);
2566 else
2526 XSetWindowBackground (dpy, scrollBar.win, pix_colors[Color_border]); 2567 XSetWindowBackground (dpy, scrollBar.win, pix_colors[Color_border]);
2527 scrollBar.state = STATE_IDLE; 2568 scrollBar.state = SB_STATE_IDLE;
2528 scrollBar.show (0); 2569 scrollBar.show (0);
2529 } 2570 }
2530 2571
2531#endif 2572 if (refresh)
2532 2573 {
2533 /* bgPixmap.apply () does not do the following : */
2534 scr_clear (); 2574 scr_clear ();
2535 scr_touch (true); 2575 scr_touch (true);
2576 }
2536 want_refresh = 1; 2577 want_refresh = 1;
2537} 2578}
2538 2579
2539/* ------------------------------------------------------------------------- */ 2580/* ------------------------------------------------------------------------- */
2540void 2581void
2626 */ 2667 */
2627#if 0 2668#if 0
2628void 2669void
2629rxvt_term::scr_dump (int fd) NOTHROW 2670rxvt_term::scr_dump (int fd) NOTHROW
2630{ 2671{
2631 int row, wrote; 2672 // if this method is needed, it can be implemented by factoring the
2632 unsigned int width, towrite; 2673 // relevant code in scr_printscreen
2633 char r1[] = "\n";
2634
2635 for (row = saveLines + top_row;
2636 row < saveLines + nrow - 1; row++)
2637 {
2638 width = row_buf[row].l >= 0 ? row_buf[row].l
2639 : ncol;
2640 for (towrite = width; towrite; towrite -= wrote)
2641 {
2642 wrote = write (fd, & (row_buf[row].t[width - towrite]),
2643 towrite);
2644 if (wrote < 0)
2645 return; /* XXX: death, no report */
2646 }
2647 if (row_buf[row].l >= 0)
2648 if (write (fd, r1, 1) <= 0)
2649 return; /* XXX: death, no report */
2650 }
2651} 2674}
2652#endif 2675#endif
2653 2676
2654/* ------------------------------------------------------------------------- * 2677/* ------------------------------------------------------------------------- *
2655 * CHARACTER SELECTION * 2678 * CHARACTER SELECTION *
2656 * ------------------------------------------------------------------------- */ 2679 * ------------------------------------------------------------------------- */
2657void 2680void
2658rxvt_term::selection_check (int check_more) NOTHROW 2681rxvt_term::selection_check (int check_more) NOTHROW
2659{ 2682{
2660 row_col_t pos;
2661
2662 if (!selection.op) 2683 if (!selection.op)
2663 return; 2684 return;
2664 2685
2665 pos.row = pos.col = 0;
2666 if (!IN_RANGE_EXC (selection.beg.row, top_row, nrow) 2686 if (!IN_RANGE_EXC (selection.beg.row, top_row, nrow)
2667 || !IN_RANGE_EXC (selection.mark.row, top_row, nrow) 2687 || !IN_RANGE_EXC (selection.mark.row, top_row, nrow)
2668 || !IN_RANGE_EXC (selection.end.row, top_row, nrow) 2688 || !IN_RANGE_EXC (selection.end.row, top_row, nrow)
2669 || (check_more == 1 2689 || (check_more == 1
2670 && current_screen == selection.screen 2690 && current_screen == selection.screen
2671 && !ROWCOL_IS_BEFORE (screen.cur, selection.beg) 2691 && !ROWCOL_IS_BEFORE (screen.cur, selection.beg)
2672 && ROWCOL_IS_BEFORE (screen.cur, selection.end)) 2692 && ROWCOL_IS_BEFORE (screen.cur, selection.end)))
2673 || (check_more == 2
2674 && ROWCOL_IS_BEFORE (selection.beg, pos)
2675 && ROWCOL_IS_AFTER (selection.end, pos))
2676 || (check_more == 3
2677 && ROWCOL_IS_AFTER (selection.end, pos))
2678 || (check_more == 4 /* screen width change */
2679 && (selection.beg.row != selection.end.row
2680 || selection.end.col > ncol)))
2681 CLEAR_SELECTION (); 2693 CLEAR_ALL_SELECTION ();
2682} 2694}
2683 2695
2684/* ------------------------------------------------------------------------- */ 2696/* ------------------------------------------------------------------------- */
2685/* 2697/*
2686 * Paste a selection direct to the command fd 2698 * Paste a selection direct to the command fd
2692 for (unsigned int i = 0; i < len; i++) 2704 for (unsigned int i = 0; i < len; i++)
2693 if (data[i] == C0_LF) 2705 if (data[i] == C0_LF)
2694 data[i] = C0_CR; 2706 data[i] = C0_CR;
2695 2707
2696 if (priv_modes & PrivMode_BracketPaste) 2708 if (priv_modes & PrivMode_BracketPaste)
2697 tt_printf ("\e[200~"); 2709 tt_printf ("\x1b[200~");
2698 2710
2699 tt_write (data, len); 2711 tt_write (data, len);
2700 2712
2701 if (priv_modes & PrivMode_BracketPaste) 2713 if (priv_modes & PrivMode_BracketPaste)
2702 tt_printf ("\e[201~"); 2714 tt_printf ("\x1b[201~");
2703} 2715}
2704 2716
2705void 2717void
2706rxvt_term::paste (char *data, unsigned int len) NOTHROW 2718rxvt_term::paste (char *data, unsigned int len) NOTHROW
2707{ 2719{
2711 tt_paste (data, len); 2723 tt_paste (data, len);
2712} 2724}
2713 2725
2714/* ------------------------------------------------------------------------- */ 2726/* ------------------------------------------------------------------------- */
2715/* 2727/*
2716 * Respond to a notification that a primary selection has been sent 2728 * Request PRIMARY, SECONDARY or CLIPBOARD selection.
2717 * EXT: SelectionNotify 2729 * if the requested selection has no owner or is empty CUT_BUFFER0 is used
2718 */ 2730 * as fallback
2719void
2720rxvt_term::selection_paste (Window win, Atom prop, bool delete_prop) NOTHROW
2721{
2722 if (prop == None) /* check for failed XConvertSelection */
2723 {
2724 if ((selection_type & Sel_CompoundText))
2725 {
2726 int selnum = selection_type & Sel_whereMask;
2727
2728 selection_type = 0;
2729 if (selnum != Sel_direct)
2730 selection_request_other (XA_STRING, selnum);
2731 }
2732
2733 if ((selection_type & Sel_UTF8String))
2734 {
2735 int selnum = selection_type & Sel_whereMask;
2736
2737 selection_type = Sel_CompoundText;
2738 if (selnum != Sel_direct)
2739 selection_request_other (xa[XA_COMPOUND_TEXT], selnum);
2740 else
2741 selection_type = 0;
2742 }
2743
2744 return;
2745 }
2746
2747 unsigned long bytes_after;
2748 XTextProperty ct;
2749
2750 if (XGetWindowProperty (dpy, win, prop,
2751 0, PROP_SIZE / 4,
2752 delete_prop, AnyPropertyType,
2753 &ct.encoding, &ct.format,
2754 &ct.nitems, &bytes_after,
2755 &ct.value) != Success)
2756 {
2757 ct.value = 0;
2758 goto bailout;
2759 }
2760
2761 if (ct.encoding == None)
2762 goto bailout;
2763
2764 if (bytes_after)
2765 {
2766 // fetch and append remaining data
2767 XTextProperty ct2;
2768
2769 if (XGetWindowProperty (dpy, win, prop,
2770 ct.nitems / 4, (bytes_after + 3) / 4,
2771 delete_prop, AnyPropertyType,
2772 &ct2.encoding, &ct2.format,
2773 &ct2.nitems, &bytes_after,
2774 &ct2.value) != Success)
2775 goto bailout;
2776
2777 // realloc should be compatible to XFree, here, and elsewhere, too
2778 ct.value = (unsigned char *)realloc (ct.value, ct.nitems + ct2.nitems + 1);
2779 memcpy (ct.value + ct.nitems, ct2.value, ct2.nitems + 1);
2780 ct.nitems += ct2.nitems;
2781
2782 XFree (ct2.value);
2783 }
2784
2785 if (ct.value == 0)
2786 goto bailout;
2787
2788 if (ct.encoding == xa[XA_INCR])
2789 {
2790 // INCR selection, start handshake
2791 if (!delete_prop)
2792 XDeleteProperty (dpy, win, prop);
2793
2794 selection_wait = Sel_incr;
2795 incr_buf_fill = 0;
2796 incr_ev.start (10);
2797
2798 goto bailout;
2799 }
2800
2801 if (ct.nitems == 0)
2802 {
2803 if (selection_wait == Sel_incr)
2804 {
2805 XFree (ct.value);
2806
2807 // finally complete, now paste the whole thing
2808 selection_wait = Sel_normal;
2809 ct.value = (unsigned char *)incr_buf;
2810 ct.nitems = incr_buf_fill;
2811 incr_buf = 0;
2812 incr_buf_size = 0;
2813 incr_ev.stop ();
2814 }
2815 else
2816 {
2817 if (selection_wait == Sel_normal
2818 && (win != display->root || prop != XA_CUT_BUFFER0)) // avoid recursion
2819 {
2820 /*
2821 * pass through again trying CUT_BUFFER0 if we've come from
2822 * XConvertSelection () but nothing was presented
2823 */
2824 selection_paste (display->root, XA_CUT_BUFFER0, False);
2825 }
2826
2827 goto bailout;
2828 }
2829 }
2830 else if (selection_wait == Sel_incr)
2831 {
2832 incr_ev.start (10);
2833
2834 while (incr_buf_fill + ct.nitems > incr_buf_size)
2835 {
2836 incr_buf_size = incr_buf_size ? incr_buf_size * 2 : 128*1024;
2837 incr_buf = (char *)realloc (incr_buf, incr_buf_size);
2838 }
2839
2840 memcpy (incr_buf + incr_buf_fill, ct.value, ct.nitems);
2841 incr_buf_fill += ct.nitems;
2842
2843 goto bailout;
2844 }
2845
2846 char **cl;
2847 int cr;
2848
2849#if !ENABLE_MINIMAL
2850 // xlib is horribly broken with respect to UTF8_STRING, and nobody cares to fix it
2851 // so recode it manually
2852 if (ct.encoding == xa[XA_UTF8_STRING])
2853 {
2854 wchar_t *w = rxvt_utf8towcs ((const char *)ct.value, ct.nitems);
2855 char *s = rxvt_wcstombs (w);
2856 free (w);
2857 // TODO: strlen == only the first element will be converted. well...
2858 paste (s, strlen (s));
2859 free (s);
2860 }
2861 else
2862#endif
2863 if (XmbTextPropertyToTextList (dpy, &ct, &cl, &cr) >= 0
2864 && cl)
2865 {
2866 for (int i = 0; i < cr; i++)
2867 paste (cl[i], strlen (cl[i]));
2868
2869 XFreeStringList (cl);
2870 }
2871 else
2872 paste ((char *)ct.value, ct.nitems); // paste raw
2873
2874bailout:
2875 XFree (ct.value);
2876
2877 if (selection_wait == Sel_normal)
2878 selection_wait = Sel_none;
2879}
2880
2881void
2882rxvt_term::incr_cb (ev::timer &w, int revents) NOTHROW
2883{
2884 selection_wait = Sel_none;
2885
2886 incr_buf_size = 0;
2887 free (incr_buf);
2888
2889 rxvt_warn ("data loss: timeout on INCR selection paste, ignoring.\n");
2890}
2891
2892void
2893rxvt_term::selection_property (Window win, Atom prop) NOTHROW
2894{
2895 if (prop == None || selection_wait != Sel_incr)
2896 return;
2897
2898 selection_paste (win, prop, true);
2899}
2900
2901/* ------------------------------------------------------------------------- */
2902/*
2903 * Request the current selection:
2904 * Order: > internal selection if available
2905 * > PRIMARY, SECONDARY, CLIPBOARD if ownership is claimed (+)
2906 * > CUT_BUFFER0
2907 * (+) if ownership is claimed but property is empty, rxvt_selection_paste ()
2908 * will auto fallback to CUT_BUFFER0
2909 * EXT: button 2 release 2731 * EXT: button 2 release
2910 */ 2732 */
2911void 2733void
2912rxvt_term::selection_request (Time tm, int selnum) NOTHROW 2734rxvt_term::selection_request (Time tm, int selnum) NOTHROW
2913{ 2735{
2914 if (selection.text && selnum == Sel_Primary) 2736 if (!selection_req)
2915 {
2916 /* internal selection */
2917 char *str = rxvt_wcstombs (selection.text, selection.len);
2918 paste (str, strlen (str));
2919 free (str);
2920 return;
2921 } 2737 {
2922 else 2738 selection_req = new rxvt_selection (display, selnum, tm, vt, xa[XA_VT_SELECTION], this);
2739 selection_req->run ();
2923 { 2740 }
2924 selection_request_time = tm;
2925 selection_wait = Sel_normal;
2926
2927#if X_HAVE_UTF8_STRING
2928 selection_type = Sel_UTF8String;
2929 if (selection_request_other (xa[XA_UTF8_STRING], selnum))
2930 return;
2931#else
2932 selection_type = Sel_CompoundText;
2933 if (selection_request_other (xa[XA_COMPOUND_TEXT], selnum))
2934 return;
2935#endif
2936 }
2937
2938 selection_wait = Sel_none; /* don't loop in selection_paste () */
2939 selection_paste (display->root, XA_CUT_BUFFER0, false);
2940}
2941
2942int
2943rxvt_term::selection_request_other (Atom target, int selnum) NOTHROW
2944{
2945 Atom sel;
2946
2947 selection_type |= selnum;
2948
2949 if (selnum == Sel_Primary)
2950 sel = XA_PRIMARY;
2951 else if (selnum == Sel_Secondary)
2952 sel = XA_SECONDARY;
2953 else
2954 sel = xa[XA_CLIPBOARD];
2955
2956 if (XGetSelectionOwner (dpy, sel) != None)
2957 {
2958 XConvertSelection (dpy, sel, target, xa[XA_VT_SELECTION],
2959 vt, selection_request_time);
2960 return 1;
2961 }
2962
2963 return 0;
2964} 2741}
2965 2742
2966/* ------------------------------------------------------------------------- */ 2743/* ------------------------------------------------------------------------- */
2967/* 2744/*
2968 * Clear all selected text 2745 * Clear all selected text
2999 * EXT: button 1 or 3 release 2776 * EXT: button 1 or 3 release
3000 */ 2777 */
3001void 2778void
3002rxvt_term::selection_make (Time tm) 2779rxvt_term::selection_make (Time tm)
3003{ 2780{
3004 int i; 2781 int size;
3005 wchar_t *new_selection_text; 2782 wchar_t *new_selection_text;
3006 text_t *t; 2783 text_t *t;
3007 2784
3008 switch (selection.op) 2785 switch (selection.op)
3009 { 2786 {
3025 return; /* nothing selected, go away */ 2802 return; /* nothing selected, go away */
3026 2803
3027 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)))
3028 return; 2805 return;
3029 2806
3030 i = (selection.end.row - selection.beg.row + 1) * (ncol + 1); 2807 size = (selection.end.row - selection.beg.row + 1) * (ncol + 1);
3031 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));
3032 2809
3033 int ofs = 0; 2810 int ofs = 0;
3034 int extra = 0; 2811 int extra = 0;
3035 2812
3036 int col = selection.beg.col; 2813 int col = selection.beg.col;
3042 { 2819 {
3043#if !ENABLE_MINIMAL 2820#if !ENABLE_MINIMAL
3044 if (selection.rect) 2821 if (selection.rect)
3045 { 2822 {
3046 col = selection.beg.col; 2823 col = selection.beg.col;
3047 end_col = ncol + 1; 2824 end_col = selection.end.col;
3048 } 2825 }
3049 else 2826 else
3050#endif 2827#endif
3051 end_col = ROW(row).l; 2828 end_col = ROW(row).l;
3052 2829
3053 col = max (col, 0); 2830 col = max (col, 0);
3054 2831
3055 if (row == selection.end.row 2832 if (row == selection.end.row)
3056#if !ENABLE_MINIMAL
3057 || selection.rect
3058#endif
3059 )
3060 min_it (end_col, selection.end.col); 2833 min_it (end_col, selection.end.col);
3061 2834
3062 t = ROW(row).t + col; 2835 t = ROW(row).t + col;
3063 2836
3064 for (; col < end_col; col++) 2837 for (; col < end_col; col++)
3072 2845
3073 extra -= (len - 1); 2846 extra -= (len - 1);
3074 2847
3075 if (extra < 0) 2848 if (extra < 0)
3076 { 2849 {
3077 extra += i; 2850 extra += size;
3078 i += i; 2851 size += size;
3079 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));
3080 } 2853 }
3081 2854
3082 ofs += rxvt_composite.expand (*t++, new_selection_text + ofs); 2855 ofs += rxvt_composite.expand (*t++, new_selection_text + ofs);
3083 } 2856 }
3084#endif 2857#endif
3096 2869
3097 new_selection_text[ofs++] = C0_LF; 2870 new_selection_text[ofs++] = C0_LF;
3098 } 2871 }
3099 else 2872 else
3100#endif 2873#endif
3101 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))
3102 new_selection_text[ofs++] = C0_LF; 2877 new_selection_text[ofs++] = C0_LF;
3103 } 2878 }
3104
3105 if (end_col != selection.end.col)
3106 new_selection_text[ofs++] = C0_LF;
3107 2879
3108 new_selection_text[ofs] = 0; 2880 new_selection_text[ofs] = 0;
3109 2881
3110 if (ofs == 0) 2882 if (ofs == 0)
3111 { 2883 {
3617 * EXT: SelectionRequest 3389 * EXT: SelectionRequest
3618 */ 3390 */
3619void 3391void
3620rxvt_term::selection_send (const XSelectionRequestEvent &rq) NOTHROW 3392rxvt_term::selection_send (const XSelectionRequestEvent &rq) NOTHROW
3621{ 3393{
3394 Atom property = rq.property == None ? rq.target : rq.property;
3622 XSelectionEvent ev; 3395 XSelectionEvent ev;
3623 3396
3624 ev.type = SelectionNotify; 3397 ev.type = SelectionNotify;
3625 ev.property = None; 3398 ev.property = None;
3626 ev.display = rq.display; 3399 ev.display = rq.display;
3641 *target++ = xa[XA_COMPOUND_TEXT]; 3414 *target++ = xa[XA_COMPOUND_TEXT];
3642#if X_HAVE_UTF8_STRING 3415#if X_HAVE_UTF8_STRING
3643 *target++ = xa[XA_UTF8_STRING]; 3416 *target++ = xa[XA_UTF8_STRING];
3644#endif 3417#endif
3645 3418
3646 XChangeProperty (dpy, rq.requestor, rq.property, XA_ATOM, 3419 XChangeProperty (dpy, rq.requestor, property, XA_ATOM,
3647 32, PropModeReplace, 3420 32, PropModeReplace,
3648 (unsigned char *)target_list, target - target_list); 3421 (unsigned char *)target_list, target - target_list);
3649 ev.property = rq.property; 3422 ev.property = property;
3650 } 3423 }
3651#if TODO // TODO 3424#if TODO // TODO
3652 else if (rq.target == xa[XA_MULTIPLE]) 3425 else if (rq.target == xa[XA_MULTIPLE])
3653 { 3426 {
3654 /* TODO: Handle MULTIPLE */ 3427 /* TODO: Handle MULTIPLE */
3655 } 3428 }
3656#endif 3429#endif
3657 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)
3658 { 3431 {
3659 XChangeProperty (dpy, rq.requestor, rq.property, rq.target, 3432 XChangeProperty (dpy, rq.requestor, property, rq.target,
3660 32, PropModeReplace, (unsigned char *)&selection_time, 1); 3433 32, PropModeReplace, (unsigned char *)&selection_time, 1);
3661 ev.property = rq.property; 3434 ev.property = property;
3662 } 3435 }
3663 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)
3664 { 3437 {
3665 XChangeProperty (dpy, rq.requestor, rq.property, rq.target, 3438 XChangeProperty (dpy, rq.requestor, property, rq.target,
3666 32, PropModeReplace, (unsigned char *)&clipboard_time, 1); 3439 32, PropModeReplace, (unsigned char *)&clipboard_time, 1);
3667 ev.property = rq.property; 3440 ev.property = property;
3668 } 3441 }
3669 else if (rq.target == XA_STRING 3442 else if (rq.target == XA_STRING
3670 || rq.target == xa[XA_TEXT] 3443 || rq.target == xa[XA_TEXT]
3671 || rq.target == xa[XA_COMPOUND_TEXT] 3444 || rq.target == xa[XA_COMPOUND_TEXT]
3672 || rq.target == xa[XA_UTF8_STRING] 3445 || rq.target == xa[XA_UTF8_STRING]
3743 ct.value = (unsigned char *)cl; 3516 ct.value = (unsigned char *)cl;
3744 ct.nitems = selectlen; 3517 ct.nitems = selectlen;
3745 ct.encoding = target; 3518 ct.encoding = target;
3746 } 3519 }
3747 3520
3748 XChangeProperty (dpy, rq.requestor, rq.property, 3521 XChangeProperty (dpy, rq.requestor, property,
3749 ct.encoding, 8, PropModeReplace, 3522 ct.encoding, 8, PropModeReplace,
3750 ct.value, (int)ct.nitems); 3523 ct.value, (int)ct.nitems);
3751 ev.property = rq.property; 3524 ev.property = property;
3752 3525
3753 if (freect) 3526 if (freect)
3754 XFree (ct.value); 3527 XFree (ct.value);
3755 } 3528 }
3756 3529

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines