1 | /*--------------------------------*-C-*--------------------------------------* |
1 | /*--------------------------------*-C-*--------------------------------------* |
2 | * File: screen.c |
2 | * File: screen.c |
3 | *---------------------------------------------------------------------------* |
3 | *---------------------------------------------------------------------------* |
4 | * $Id: screen.C,v 1.6 2003/12/02 21:49:46 pcg Exp $ |
4 | * $Id: screen.C,v 1.7 2003/12/16 23:04:13 pcg Exp $ |
5 | * |
5 | * |
6 | * Copyright (c) 1997-2001 Geoff Wing <gcw@pobox.com> |
6 | * Copyright (c) 1997-2001 Geoff Wing <gcw@pobox.com> |
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 |
… | |
… | |
2395 | |
2395 | |
2396 | /* ------------------------------------------------------------------------- */ |
2396 | /* ------------------------------------------------------------------------- */ |
2397 | /* |
2397 | /* |
2398 | * Paste a selection direct to the command fd |
2398 | * Paste a selection direct to the command fd |
2399 | */ |
2399 | */ |
2400 | /* INTPROTO */ |
|
|
2401 | void |
2400 | void |
2402 | rxvt_PasteIt (pR_ const unsigned char *data, unsigned int nitems) |
2401 | rxvt_term::paste (const unsigned char *data, unsigned int len) |
2403 | { |
2402 | { |
2404 | unsigned int i, j, n; |
2403 | unsigned int i, j, n; |
2405 | unsigned char *ds = (unsigned char *)rxvt_malloc (PROP_SIZE); |
2404 | unsigned char *ds = (unsigned char *)rxvt_malloc (PROP_SIZE); |
2406 | |
2405 | |
2407 | /* convert normal newline chars into common keyboard Return key sequence */ |
2406 | /* convert normal newline chars into common keyboard Return key sequence */ |
2408 | for (i = 0; i < nitems; i += PROP_SIZE) |
2407 | for (i = 0; i < len; i += PROP_SIZE) |
2409 | { |
2408 | { |
2410 | n = min (nitems - i, PROP_SIZE); |
2409 | n = min (len - i, PROP_SIZE); |
2411 | MEMCPY (ds, data + i, n); |
2410 | MEMCPY (ds, data + i, n); |
|
|
2411 | |
2412 | for (j = 0; j < n; j++) |
2412 | for (j = 0; j < n; j++) |
2413 | if (ds[j] == '\n') |
2413 | if (ds[j] == '\n') |
2414 | ds[j] = '\r'; |
2414 | ds[j] = '\r'; |
|
|
2415 | |
2415 | R->tt_write (ds, (int)n); |
2416 | tt_write (ds, (int)n); |
2416 | } |
2417 | } |
2417 | |
2418 | |
2418 | free(ds); |
2419 | free(ds); |
2419 | } |
2420 | } |
2420 | |
2421 | |
… | |
… | |
2425 | */ |
2426 | */ |
2426 | /* EXTPROTO */ |
2427 | /* EXTPROTO */ |
2427 | int |
2428 | int |
2428 | rxvt_selection_paste(pR_ Window win, Atom prop, Bool delete_prop) |
2429 | rxvt_selection_paste(pR_ Window win, Atom prop, Bool delete_prop) |
2429 | { |
2430 | { |
2430 | long nread = 0; |
2431 | long nread = 0; |
2431 | unsigned long bytes_after; |
2432 | unsigned long bytes_after; |
2432 | XTextProperty ct; |
2433 | XTextProperty ct; |
2433 | #ifdef MULTICHAR_SET |
2434 | int dummy_count; |
2434 | int dummy_count; |
2435 | char **cl; |
2435 | char **cl; |
|
|
2436 | #endif |
|
|
2437 | |
2436 | |
2438 | D_SELECT((stderr, "rxvt_selection_paste(%08lx, %lu, %d), wait=%2x", win, (unsigned long)prop, (int)delete_prop, R->selection_wait)); |
2437 | D_SELECT((stderr, "rxvt_selection_paste(%08lx, %lu, %d), wait=%2x", win, (unsigned long)prop, (int)delete_prop, R->selection_wait)); |
2439 | |
2438 | |
2440 | if (prop == None) { /* check for failed XConvertSelection */ |
2439 | if (prop == None) /* check for failed XConvertSelection */ |
2441 | #ifdef MULTICHAR_SET |
2440 | { |
2442 | if ((R->selection_type & Sel_CompoundText)) { |
2441 | if ((R->selection_type & Sel_CompoundText)) |
|
|
2442 | { |
2443 | int selnum = R->selection_type & Sel_whereMask; |
2443 | int selnum = R->selection_type & Sel_whereMask; |
2444 | |
2444 | |
2445 | R->selection_type = 0; |
2445 | R->selection_type = 0; |
2446 | if (selnum != Sel_direct) |
2446 | if (selnum != Sel_direct) |
2447 | rxvt_selection_request_other(aR_ XA_STRING, selnum); |
2447 | rxvt_selection_request_other(aR_ XA_STRING, selnum); |
|
|
2448 | } |
2448 | } |
2449 | |
2449 | #endif |
|
|
2450 | return 0; |
2450 | return 0; |
2451 | } |
2451 | } |
|
|
2452 | |
2452 | for (;;) { |
2453 | for (;;) |
|
|
2454 | { |
2453 | if (XGetWindowProperty(R->Xdisplay, win, prop, (long)(nread / 4), |
2455 | if (XGetWindowProperty(R->Xdisplay, win, prop, (long)(nread / 4), |
2454 | (long)(PROP_SIZE / 4), delete_prop, |
2456 | (long)(PROP_SIZE / 4), delete_prop, |
2455 | AnyPropertyType, &ct.encoding, &ct.format, |
2457 | AnyPropertyType, &ct.encoding, &ct.format, |
2456 | &ct.nitems, &bytes_after, |
2458 | &ct.nitems, &bytes_after, |
2457 | &ct.value) != Success) |
2459 | &ct.value) != Success) |
2458 | break; |
2460 | break; |
|
|
2461 | |
2459 | if (ct.encoding == 0) { |
2462 | if (ct.encoding == 0) |
|
|
2463 | { |
2460 | D_SELECT((stderr, "rxvt_selection_paste: property didn't exist!")); |
2464 | D_SELECT((stderr, "rxvt_selection_paste: property didn't exist!")); |
2461 | break; |
2465 | break; |
2462 | } |
2466 | } |
|
|
2467 | |
2463 | if (ct.value == NULL) { |
2468 | if (ct.value == NULL) |
|
|
2469 | { |
2464 | D_SELECT((stderr, "rxvt_selection_paste: property shooting blanks!")); |
2470 | D_SELECT((stderr, "rxvt_selection_paste: property shooting blanks!")); |
2465 | continue; |
2471 | continue; |
2466 | } |
2472 | } |
|
|
2473 | |
2467 | if (ct.nitems == 0) { |
2474 | if (ct.nitems == 0) |
|
|
2475 | { |
2468 | D_SELECT((stderr, "rxvt_selection_paste: property empty - also INCR end")); |
2476 | D_SELECT((stderr, "rxvt_selection_paste: property empty - also INCR end")); |
2469 | if (R->selection_wait == Sel_normal && nread == 0) { |
2477 | if (R->selection_wait == Sel_normal && nread == 0) |
|
|
2478 | { |
2470 | /* |
2479 | /* |
2471 | * pass through again trying CUT_BUFFER0 if we've come from |
2480 | * pass through again trying CUT_BUFFER0 if we've come from |
2472 | * XConvertSelection() but nothing was presented |
2481 | * XConvertSelection() but nothing was presented |
2473 | */ |
2482 | */ |
2474 | D_SELECT((stderr, "rxvt_selection_request: pasting CUT_BUFFER0")); |
2483 | D_SELECT((stderr, "rxvt_selection_request: pasting CUT_BUFFER0")); |
2475 | rxvt_selection_paste(aR_ Xroot, XA_CUT_BUFFER0, False); |
2484 | rxvt_selection_paste (aR_ Xroot, XA_CUT_BUFFER0, False); |
2476 | } |
2485 | } |
|
|
2486 | |
2477 | nread = -1; /* discount any previous stuff */ |
2487 | nread = -1; /* discount any previous stuff */ |
2478 | break; |
2488 | break; |
2479 | } |
2489 | } |
|
|
2490 | |
2480 | nread += ct.nitems; |
2491 | nread += ct.nitems; |
2481 | #ifdef MULTICHAR_SET |
|
|
2482 | if (XmbTextPropertyToTextList(R->Xdisplay, &ct, &cl, |
2492 | if (XmbTextPropertyToTextList (R->Xdisplay, &ct, &cl, |
2483 | &dummy_count) == Success && cl) { |
2493 | &dummy_count) == Success && cl) |
2484 | rxvt_PasteIt(aR_ cl[0], STRLEN(cl[0])); |
2494 | { |
|
|
2495 | R->paste ((unsigned char *)cl[0], STRLEN (cl[0])); |
2485 | XFreeStringList(cl); |
2496 | XFreeStringList (cl); |
|
|
2497 | } |
2486 | } else |
2498 | else |
2487 | #endif |
2499 | R->paste (ct.value, ct.nitems); |
2488 | rxvt_PasteIt(aR_ ct.value, (unsigned int)ct.nitems); |
2500 | |
2489 | if (bytes_after == 0) |
2501 | if (bytes_after == 0) |
2490 | break; |
2502 | break; |
|
|
2503 | |
2491 | XFree(ct.value); |
2504 | XFree (ct.value); |
2492 | } |
2505 | } |
|
|
2506 | |
2493 | if (ct.value) |
2507 | if (ct.value) |
2494 | XFree(ct.value); |
2508 | XFree (ct.value); |
|
|
2509 | |
2495 | if (R->selection_wait == Sel_normal) |
2510 | if (R->selection_wait == Sel_normal) |
2496 | R->selection_wait = Sel_none; |
2511 | R->selection_wait = Sel_none; |
|
|
2512 | |
2497 | D_SELECT((stderr, "rxvt_selection_paste: bytes written: %ld", nread)); |
2513 | D_SELECT((stderr, "rxvt_selection_paste: bytes written: %ld", nread)); |
2498 | return (int)nread; |
2514 | return (int)nread; |
|
|
2515 | } |
|
|
2516 | |
|
|
2517 | void |
|
|
2518 | rxvt_term::incr_cb (time_watcher &w) |
|
|
2519 | { |
|
|
2520 | w.stop (); |
|
|
2521 | selection_wait = Sel_none; |
|
|
2522 | |
|
|
2523 | rxvt_print_error("data loss: timeout on INCR selection paste"); |
2499 | } |
2524 | } |
2500 | |
2525 | |
2501 | /* |
2526 | /* |
2502 | * INCR support originally provided by Paul Sheer <psheer@obsidian.co.za> |
2527 | * INCR support originally provided by Paul Sheer <psheer@obsidian.co.za> |
2503 | */ |
2528 | */ |
… | |
… | |
2535 | } else if (R->selection_wait == Sel_incr) { |
2560 | } else if (R->selection_wait == Sel_incr) { |
2536 | reget_time = 1; |
2561 | reget_time = 1; |
2537 | if (rxvt_selection_paste(aR_ win, prop, True) == -1) { |
2562 | if (rxvt_selection_paste(aR_ win, prop, True) == -1) { |
2538 | D_SELECT((stderr, "rxvt_selection_property: INCR: clean end")); |
2563 | D_SELECT((stderr, "rxvt_selection_property: INCR: clean end")); |
2539 | R->selection_wait = Sel_none; |
2564 | R->selection_wait = Sel_none; |
2540 | R->timeout[TIMEOUT_INCR].tv_sec = 0; /* turn off timer */ |
2565 | R->incr_ev.stop (); |
2541 | } |
2566 | } |
2542 | } |
2567 | } |
2543 | if (reget_time) { /* received more data so reget time */ |
2568 | if (reget_time) /* received more data so reget time */ |
2544 | (void)gettimeofday(&(R->timeout[TIMEOUT_INCR]), NULL); |
2569 | R->incr_ev.start (NOW + 10); |
2545 | R->timeout[TIMEOUT_INCR].tv_sec += 10; /* ten seconds wait */ |
|
|
2546 | } |
|
|
2547 | } |
2570 | } |
2548 | /* ------------------------------------------------------------------------- */ |
2571 | /* ------------------------------------------------------------------------- */ |
2549 | /* |
2572 | /* |
2550 | * Request the current selection: |
2573 | * Request the current selection: |
2551 | * Order: > internal selection if available |
2574 | * Order: > internal selection if available |
… | |
… | |
2563 | if (x < 0 || x >= R->TermWin.width || y < 0 || y >= R->TermWin.height) |
2586 | if (x < 0 || x >= R->TermWin.width || y < 0 || y >= R->TermWin.height) |
2564 | return; /* outside window */ |
2587 | return; /* outside window */ |
2565 | |
2588 | |
2566 | if (R->selection.text != NULL) { /* internal selection */ |
2589 | if (R->selection.text != NULL) { /* internal selection */ |
2567 | D_SELECT((stderr, "rxvt_selection_request: pasting internal")); |
2590 | D_SELECT((stderr, "rxvt_selection_request: pasting internal")); |
2568 | rxvt_PasteIt(aR_ R->selection.text, R->selection.len); |
2591 | R->paste (R->selection.text, R->selection.len); |
2569 | return; |
2592 | return; |
2570 | } else { |
2593 | } else { |
2571 | int i; |
2594 | int i; |
2572 | |
2595 | |
2573 | R->selection_request_time = tm; |
2596 | R->selection_request_time = tm; |
2574 | R->selection_wait = Sel_normal; |
2597 | R->selection_wait = Sel_normal; |
2575 | for (i = Sel_Primary; i <= Sel_Clipboard; i++) { |
2598 | for (i = Sel_Primary; i <= Sel_Clipboard; i++) { |
2576 | #ifdef MULTICHAR_SET |
|
|
2577 | R->selection_type = Sel_CompoundText; |
2599 | R->selection_type = Sel_CompoundText; |
2578 | #else |
|
|
2579 | R->selection_type = 0; |
|
|
2580 | #endif |
|
|
2581 | if (rxvt_selection_request_other(aR_ |
2600 | if (rxvt_selection_request_other(aR_ R->xa[XA_COMPOUND_TEXT], i)) |
2582 | #ifdef MULTICHAR_SET |
|
|
2583 | R->xa[XA_COMPOUND_TEXT], |
|
|
2584 | #else |
|
|
2585 | XA_STRING, |
|
|
2586 | #endif |
|
|
2587 | i)) |
|
|
2588 | return; |
2601 | return; |
2589 | } |
2602 | } |
2590 | } |
2603 | } |
2591 | R->selection_wait = Sel_none; /* don't loop in rxvt_selection_paste() */ |
2604 | R->selection_wait = Sel_none; /* don't loop in rxvt_selection_paste() */ |
2592 | D_SELECT((stderr, "rxvt_selection_request: pasting CUT_BUFFER0")); |
2605 | D_SELECT((stderr, "rxvt_selection_request: pasting CUT_BUFFER0")); |
… | |
… | |
2801 | */ |
2814 | */ |
2802 | |
2815 | |
2803 | /* what do we want: spaces/tabs are delimiters or cutchars or non-cutchars */ |
2816 | /* what do we want: spaces/tabs are delimiters or cutchars or non-cutchars */ |
2804 | #define DELIMIT_TEXT(x) \ |
2817 | #define DELIMIT_TEXT(x) \ |
2805 | (((x) == ' ' || (x) == '\t') ? 2 : (STRCHR(R->rs[Rs_cutchars], (x)) != NULL)) |
2818 | (((x) == ' ' || (x) == '\t') ? 2 : (STRCHR(R->rs[Rs_cutchars], (x)) != NULL)) |
2806 | #ifdef MULTICHAR_SET |
|
|
2807 | # define DELIMIT_REND(x) (((x) & RS_multiMask) ? 1 : 0) |
|
|
2808 | #else |
|
|
2809 | # define DELIMIT_REND(x) 1 |
2819 | #define DELIMIT_REND(x) 1 |
2810 | #endif |
|
|
2811 | |
2820 | |
2812 | /* INTPROTO */ |
2821 | /* INTPROTO */ |
2813 | void |
2822 | void |
2814 | rxvt_selection_delimit_word(pR_ enum page_dirn dirn, const row_col_t *mark, row_col_t *ret) |
2823 | rxvt_selection_delimit_word(pR_ enum page_dirn dirn, const row_col_t *mark, row_col_t *ret) |
2815 | { |
2824 | { |