comparison src/select-x.c @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents 8de8e3f6228a
children 576fb035e263
comparison
equal deleted inserted replaced
441:72a7cfa4a488 442:abe6d1db359e
136 if (EQ (sym, QCUT_BUFFER6)) return XA_CUT_BUFFER6; 136 if (EQ (sym, QCUT_BUFFER6)) return XA_CUT_BUFFER6;
137 if (EQ (sym, QCUT_BUFFER7)) return XA_CUT_BUFFER7; 137 if (EQ (sym, QCUT_BUFFER7)) return XA_CUT_BUFFER7;
138 #endif /* CUT_BUFFER_SUPPORT */ 138 #endif /* CUT_BUFFER_SUPPORT */
139 139
140 { 140 {
141 CONST char *nameext; 141 const char *nameext;
142 TO_EXTERNAL_FORMAT (LISP_STRING, Fsymbol_name (sym), 142 LISP_STRING_TO_EXTERNAL (Fsymbol_name (sym), nameext, Qctext);
143 C_STRING_ALLOCA, nameext,
144 Qctext);
145 return XInternAtom (display, nameext, only_if_exists ? True : False); 143 return XInternAtom (display, nameext, only_if_exists ? True : False);
146 } 144 }
147 } 145 }
148 146
149 147
198 } 196 }
199 } 197 }
200 198
201 199
202 /* Do protocol to assert ourself as a selection owner. 200 /* Do protocol to assert ourself as a selection owner.
203 Update the Vselection_alist so that we can reply to later requests for
204 our selection.
205 */ 201 */
206 static Lisp_Object 202 static Lisp_Object
207 x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value) 203 x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
204 Lisp_Object how_to_add, Lisp_Object selection_type)
208 { 205 {
209 struct device *d = decode_x_device (Qnil); 206 struct device *d = decode_x_device (Qnil);
210 Display *display = DEVICE_X_DISPLAY (d); 207 Display *display = DEVICE_X_DISPLAY (d);
211 struct frame *sel_frame = selected_frame (); 208 struct frame *sel_frame = selected_frame ();
212 Window selecting_window = XtWindow (FRAME_X_TEXT_WIDGET (sel_frame)); 209 Window selecting_window = XtWindow (FRAME_X_TEXT_WIDGET (sel_frame));
227 224
228 /* We do NOT use time_to_lisp() here any more, like we used to. 225 /* We do NOT use time_to_lisp() here any more, like we used to.
229 That assumed equivalence of time_t and Time, which is not 226 That assumed equivalence of time_t and Time, which is not
230 necessarily the case (e.g. under OSF on the Alphas, where 227 necessarily the case (e.g. under OSF on the Alphas, where
231 Time is a 64-bit quantity and time_t is a 32-bit quantity). 228 Time is a 64-bit quantity and time_t is a 32-bit quantity).
232 229
233 Opaque pointers are the clean way to go here. 230 Opaque pointers are the clean way to go here.
234 */ 231 */
235 selection_time = make_opaque (&thyme, sizeof (thyme)); 232 selection_time = make_opaque (&thyme, sizeof (thyme));
236 233
237 #ifdef MOTIF_CLIPBOARDS 234 #ifdef MOTIF_CLIPBOARDS
250 static void 247 static void
251 hack_motif_clipboard_selection (Atom selection_atom, 248 hack_motif_clipboard_selection (Atom selection_atom,
252 Lisp_Object selection_value, 249 Lisp_Object selection_value,
253 Time thyme, 250 Time thyme,
254 Display *display, 251 Display *display,
255 Window selecting_window) 252 Window selecting_window)
256 /* Bool owned_p)*/ 253 /* Bool owned_p)*/
257 { 254 {
258 struct device *d = get_device_from_display (display); 255 struct device *d = get_device_from_display (display);
259 /* Those Motif wankers can't be bothered to follow the ICCCM, and do 256 /* Those Motif wankers can't be bothered to follow the ICCCM, and do
260 their own non-Xlib non-Xt clipboard processing. So we have to do 257 their own non-Xlib non-Xt clipboard processing. So we have to do
285 #else 282 #else
286 int dataid; /* 1.2 wants long, but 1.1.5 wants int... */ 283 int dataid; /* 1.2 wants long, but 1.1.5 wants int... */
287 #endif 284 #endif
288 XmString fmh; 285 XmString fmh;
289 String encoding = "STRING"; 286 String encoding = "STRING";
290 CONST Extbyte *data = XSTRING_DATA (selection_value); 287 const Extbyte *data = XSTRING_DATA (selection_value);
291 Extcount bytes = XSTRING_LENGTH (selection_value); 288 Extcount bytes = XSTRING_LENGTH (selection_value);
292 289
293 #ifdef MULE 290 #ifdef MULE
294 { 291 {
295 enum { ASCII, LATIN_1, WORLD } chartypes = ASCII; 292 enum { ASCII, LATIN_1, WORLD } chartypes = ASCII;
296 CONST Bufbyte *ptr = data, *end = ptr + bytes; 293 const Bufbyte *ptr = data, *end = ptr + bytes;
297 /* Optimize for the common ASCII case */ 294 /* Optimize for the common ASCII case */
298 while (ptr <= end) 295 while (ptr <= end)
299 { 296 {
300 if (BYTE_ASCII_P (*ptr)) 297 if (BYTE_ASCII_P (*ptr))
301 { 298 {
373 { 370 {
374 case XmCR_CLIPBOARD_DATA_REQUEST: 371 case XmCR_CLIPBOARD_DATA_REQUEST:
375 { 372 {
376 Display *dpy = XtDisplay (widget); 373 Display *dpy = XtDisplay (widget);
377 Window window = (Window) *private_id; 374 Window window = (Window) *private_id;
378 Lisp_Object selection = assq_no_quit (QCLIPBOARD, Vselection_alist); 375 Lisp_Object selection = select_convert_out (QCLIPBOARD, Qnil, Qnil);
379 if (NILP (selection)) abort (); 376
380 selection = XCDR (selection); 377 /* Whichever lazy git wrote this originally just called abort()
381 if (!STRINGP (selection)) abort (); 378 when anything didn't go their way... */
379
380 /* Try some other text types */
381 if (NILP (selection))
382 selection = select_convert_out (QCLIPBOARD, QSTRING, Qnil);
383 if (NILP (selection))
384 selection = select_convert_out (QCLIPBOARD, QTEXT, Qnil);
385 if (NILP (selection))
386 selection = select_convert_out (QCLIPBOARD, QCOMPOUND_TEXT, Qnil);
387
388 if (CONSP (selection) && SYMBOLP (XCAR (selection))
389 && (EQ (XCAR (selection), QSTRING)
390 || EQ (XCAR (selection), QTEXT)
391 || EQ (XCAR (selection), QCOMPOUND_TEXT)))
392 selection = XCDR (selection);
393
394 if (NILP (selection))
395 signal_error (Qselection_conversion_error,
396 build_string ("no selection"));
397
398 if (!STRINGP (selection))
399 signal_error (Qselection_conversion_error,
400 build_string ("couldn't convert selection to string"));
401
402
382 XmClipboardCopyByName (dpy, window, *data_id, 403 XmClipboardCopyByName (dpy, window, *data_id,
383 (char *) XSTRING_DATA (selection), 404 (char *) XSTRING_DATA (selection),
384 XSTRING_LENGTH (selection) + 1, 405 XSTRING_LENGTH (selection) + 1,
385 0); 406 0);
386 } 407 }
544 */ 565 */
545 void 566 void
546 x_handle_selection_request (XSelectionRequestEvent *event) 567 x_handle_selection_request (XSelectionRequestEvent *event)
547 { 568 {
548 /* This function can GC */ 569 /* This function can GC */
549 struct gcpro gcpro1, gcpro2, gcpro3; 570 struct gcpro gcpro1, gcpro2;
550 Lisp_Object local_selection_data = Qnil; 571 Lisp_Object temp_obj;
551 Lisp_Object selection_symbol; 572 Lisp_Object selection_symbol;
552 Lisp_Object target_symbol = Qnil; 573 Lisp_Object target_symbol = Qnil;
553 Lisp_Object converted_selection = Qnil; 574 Lisp_Object converted_selection = Qnil;
554 Time local_selection_time; 575 Time local_selection_time;
555 Lisp_Object successful_p = Qnil; 576 Lisp_Object successful_p = Qnil;
556 int count; 577 int count;
557 struct device *d = get_device_from_display (event->display); 578 struct device *d = get_device_from_display (event->display);
558 579
559 GCPRO3 (local_selection_data, converted_selection, target_symbol); 580 GCPRO2 (converted_selection, target_symbol);
560 581
561 selection_symbol = x_atom_to_symbol (d, event->selection); 582 selection_symbol = x_atom_to_symbol (d, event->selection);
562 583 target_symbol = x_atom_to_symbol (d, event->target);
563 local_selection_data = assq_no_quit (selection_symbol, Vselection_alist); 584
564 585 #if 0 /* #### MULTIPLE doesn't work yet */
565 #if 0 586 if (EQ (target_symbol, QMULTIPLE))
566 /* This list isn't user-visible, so it can't "go bad." */ 587 target_symbol = fetch_multiple_target (event);
567 assert (CONSP (local_selection_data)); 588 #endif
568 assert (CONSP (XCDR (local_selection_data))); 589
569 assert (CONSP (XCDR (XCDR (local_selection_data)))); 590 temp_obj = Fget_selection_timestamp (selection_symbol);
570 assert (NILP (XCDR (XCDR (XCDR (local_selection_data))))); 591
571 assert (CONSP (XCAR (XCDR (XCDR (local_selection_data))))); 592 if (NILP (temp_obj))
572 assert (INTP (XCAR (XCAR (XCDR (XCDR (local_selection_data)))))); 593 {
573 assert (INTP (XCDR (XCAR (XCDR (XCDR (local_selection_data)))))); 594 /* We don't appear to have the selection. */
574 #endif
575
576 if (NILP (local_selection_data))
577 {
578 /* Someone asked for the selection, but we don't have it any more. */
579 x_decline_selection_request (event); 595 x_decline_selection_request (event);
596
580 goto DONE_LABEL; 597 goto DONE_LABEL;
581 } 598 }
582 599
583 local_selection_time = 600 local_selection_time = * (Time *) XOPAQUE_DATA (temp_obj);
584 * (Time *) XOPAQUE_DATA (XCAR (XCDR (XCDR (local_selection_data))));
585 601
586 if (event->time != CurrentTime && 602 if (event->time != CurrentTime &&
587 local_selection_time > event->time) 603 local_selection_time > event->time)
588 { 604 {
589 /* Someone asked for the selection, and we have one, but not the one 605 /* Someone asked for the selection, and we have one, but not the one
590 they're looking for. */ 606 they're looking for. */
591 x_decline_selection_request (event); 607 x_decline_selection_request (event);
592 goto DONE_LABEL; 608 goto DONE_LABEL;
593 } 609 }
594 610
611 converted_selection = select_convert_out (selection_symbol,
612 target_symbol, Qnil);
613
614 /* #### Is this the right thing to do? I'm no X expert. -- ajh */
615 if (NILP (converted_selection))
616 {
617 /* We don't appear to have a selection in that data type. */
618 x_decline_selection_request (event);
619 goto DONE_LABEL;
620 }
621
595 count = specpdl_depth (); 622 count = specpdl_depth ();
596 record_unwind_protect (x_selection_request_lisp_error, 623 record_unwind_protect (x_selection_request_lisp_error,
597 make_opaque_ptr (event)); 624 make_opaque_ptr (event));
598 target_symbol = x_atom_to_symbol (d, event->target); 625
599 626 {
600 #if 0 /* #### MULTIPLE doesn't work yet */ 627 unsigned char *data;
601 if (EQ (target_symbol, QMULTIPLE)) 628 unsigned int size;
602 target_symbol = fetch_multiple_target (event); 629 int format;
603 #endif 630 Atom type;
604 631 lisp_data_to_selection_data (d, converted_selection,
605 /* Convert lisp objects back into binary data */ 632 &data, &type, &size, &format);
606 633
607 converted_selection = 634 x_reply_selection_request (event, format, data, size, type);
608 get_local_selection (selection_symbol, target_symbol); 635 successful_p = Qt;
609 636 /* Tell x_selection_request_lisp_error() it's cool. */
610 if (! NILP (converted_selection)) 637 event->type = 0;
611 { 638 xfree (data);
612 unsigned char *data; 639 }
613 unsigned int size; 640
614 int format;
615 Atom type;
616 lisp_data_to_selection_data (d, converted_selection,
617 &data, &type, &size, &format);
618
619 x_reply_selection_request (event, format, data, size, type);
620 successful_p = Qt;
621 /* Tell x_selection_request_lisp_error() it's cool. */ event->type = 0;
622 xfree (data);
623 }
624 unbind_to (count, Qnil); 641 unbind_to (count, Qnil);
625 642
626 DONE_LABEL: 643 DONE_LABEL:
627 644
628 UNGCPRO; 645 UNGCPRO;
629 646
630 /* Let random lisp code notice that the selection has been asked for. */ 647 /* Let random lisp code notice that the selection has been asked for. */
631 { 648 {
632 Lisp_Object rest;
633 Lisp_Object val = Vx_sent_selection_hooks; 649 Lisp_Object val = Vx_sent_selection_hooks;
634 if (!UNBOUNDP (val) && !NILP (val)) 650 if (!UNBOUNDP (val) && !NILP (val))
635 { 651 {
652 Lisp_Object rest;
636 if (CONSP (val) && !EQ (XCAR (val), Qlambda)) 653 if (CONSP (val) && !EQ (XCAR (val), Qlambda))
637 for (rest = val; !NILP (rest); rest = Fcdr (rest)) 654 for (rest = val; !NILP (rest); rest = Fcdr (rest))
638 call3 (Fcar(rest), selection_symbol, target_symbol, 655 call3 (Fcar (rest), selection_symbol, target_symbol, successful_p);
639 successful_p);
640 else 656 else
641 call3 (val, selection_symbol, target_symbol, 657 call3 (val, selection_symbol, target_symbol, successful_p);
642 successful_p);
643 } 658 }
644 } 659 }
645 } 660 }
646 661
647 662
653 Display *display = event->display; 668 Display *display = event->display;
654 struct device *d = get_device_from_display (display); 669 struct device *d = get_device_from_display (display);
655 Atom selection = event->selection; 670 Atom selection = event->selection;
656 Time changed_owner_time = event->time; 671 Time changed_owner_time = event->time;
657 672
658 Lisp_Object selection_symbol, local_selection_data; 673 Lisp_Object selection_symbol, local_selection_time_lisp;
659 Time local_selection_time; 674 Time local_selection_time;
660 675
661 selection_symbol = x_atom_to_symbol (d, selection); 676 selection_symbol = x_atom_to_symbol (d, selection);
662 677
663 local_selection_data = assq_no_quit (selection_symbol, Vselection_alist); 678 local_selection_time_lisp = Fget_selection_timestamp (selection_symbol);
664 679
665 /* Well, we already believe that we don't own it, so that's just fine. */ 680 /* We don't own the selection, so that's fine. */
666 if (NILP (local_selection_data)) return; 681 if (NILP (local_selection_time_lisp))
667 682 return;
668 local_selection_time = 683
669 * (Time *) XOPAQUE_DATA (XCAR (XCDR (XCDR (local_selection_data)))); 684 local_selection_time = * (Time *) XOPAQUE_DATA (local_selection_time_lisp);
670 685
671 /* This SelectionClear is for a selection that we no longer own, so we can 686 /* This SelectionClear is for a selection that we no longer own, so we can
672 disregard it. (That is, we have reasserted the selection since this 687 disregard it. (That is, we have reasserted the selection since this
673 request was generated.) 688 request was generated.)
674 */ 689 */
675 if (changed_owner_time != CurrentTime && 690 if (changed_owner_time != CurrentTime &&
676 local_selection_time > changed_owner_time) 691 local_selection_time > changed_owner_time)
677 return; 692 return;
678 693
679 handle_selection_clear (selection_symbol); 694 handle_selection_clear (selection_symbol);
680 } 695 }
681 696
682 697
683 /* This stuff is so that INCR selections are reentrant (that is, so we can 698 /* This stuff is so that INCR selections are reentrant (that is, so we can
918 error ("timed out waiting for reply from selection owner"); 933 error ("timed out waiting for reply from selection owner");
919 934
920 unbind_to (speccount, Qnil); 935 unbind_to (speccount, Qnil);
921 936
922 /* otherwise, the selection is waiting for us on the requested property. */ 937 /* otherwise, the selection is waiting for us on the requested property. */
923 return 938
924 x_get_window_property_as_lisp_data (display, requestor_window, 939 return select_convert_in (selection_symbol,
925 target_property, target_type, 940 target_type,
926 selection_atom); 941 x_get_window_property_as_lisp_data(display,
942 requestor_window,
943 target_property,
944 target_type,
945 selection_atom));
927 } 946 }
928 947
929 948
930 static void 949 static void
931 x_get_window_property (Display *display, Window window, Atom property, 950 x_get_window_property (Display *display, Window window, Atom property,
1121 1140
1122 xfree (data); 1141 xfree (data);
1123 return val; 1142 return val;
1124 } 1143 }
1125 1144
1145 /* #### These are going to move into Lisp code(!) with the aid of
1146 some new functions I'm working on - ajh */
1147
1126 /* These functions convert from the selection data read from the server into 1148 /* These functions convert from the selection data read from the server into
1127 something that we can use from elisp, and vice versa. 1149 something that we can use from elisp, and vice versa.
1128 1150
1129 Type: Format: Size: Elisp Type: 1151 Type: Format: Size: Elisp Type:
1130 ----- ------- ----- ----------- 1152 ----- ------- ----- -----------
1264 *data_ret = 0; 1286 *data_ret = 0;
1265 type = QNULL; 1287 type = QNULL;
1266 } 1288 }
1267 else if (STRINGP (obj)) 1289 else if (STRINGP (obj))
1268 { 1290 {
1269 CONST Extbyte *extval; 1291 const Extbyte *extval;
1270 Extcount extvallen; 1292 Extcount extvallen;
1271 1293
1272 TO_EXTERNAL_FORMAT (LISP_STRING, obj, 1294 TO_EXTERNAL_FORMAT (LISP_STRING, obj,
1273 ALLOCA, (extval, extvallen), 1295 ALLOCA, (extval, extvallen),
1274 (NILP (type) ? Qctext : Qbinary)); 1296 (NILP (type) ? Qctext : Qbinary));
1284 } 1306 }
1285 else if (CHARP (obj)) 1307 else if (CHARP (obj))
1286 { 1308 {
1287 Bufbyte buf[MAX_EMCHAR_LEN]; 1309 Bufbyte buf[MAX_EMCHAR_LEN];
1288 Bytecount len; 1310 Bytecount len;
1289 CONST Extbyte *extval; 1311 const Extbyte *extval;
1290 Extcount extvallen; 1312 Extcount extvallen;
1291 1313
1292 *format_ret = 8; 1314 *format_ret = 8;
1293 len = set_charptr_emchar (buf, XCHAR (obj)); 1315 len = set_charptr_emchar (buf, XCHAR (obj));
1294 TO_EXTERNAL_FORMAT (DATA, (buf, len), 1316 TO_EXTERNAL_FORMAT (DATA, (buf, len),
1465 1487
1466 XSetSelectionOwner (display, selection_atom, None, timestamp); 1488 XSetSelectionOwner (display, selection_atom, None, timestamp);
1467 } 1489 }
1468 1490
1469 static Lisp_Object 1491 static Lisp_Object
1470 x_selection_exists_p (Lisp_Object selection) 1492 x_selection_exists_p (Lisp_Object selection,
1493 Lisp_Object selection_type)
1471 { 1494 {
1472 struct device *d = decode_x_device (Qnil); 1495 struct device *d = decode_x_device (Qnil);
1473 Display *dpy = DEVICE_X_DISPLAY (d); 1496 Display *dpy = DEVICE_X_DISPLAY (d);
1474 return XGetSelectionOwner (dpy, symbol_to_x_atom (d, selection, 0)) != None ? 1497 return XGetSelectionOwner (dpy, symbol_to_x_atom (d, selection, 0)) != None ?
1475 Qt : Qnil; 1498 Qt : Qnil;
1482 1505
1483 /* Ensure that all 8 cut buffers exist. ICCCM says we gotta... */ 1506 /* Ensure that all 8 cut buffers exist. ICCCM says we gotta... */
1484 static void 1507 static void
1485 initialize_cut_buffers (Display *display, Window window) 1508 initialize_cut_buffers (Display *display, Window window)
1486 { 1509 {
1487 static unsigned CONST char * CONST data = (unsigned CONST char *) ""; 1510 static unsigned const char * const data = (unsigned const char *) "";
1488 #define FROB(atom) XChangeProperty (display, window, atom, XA_STRING, 8, \ 1511 #define FROB(atom) XChangeProperty (display, window, atom, XA_STRING, 8, \
1489 PropModeAppend, data, 0) 1512 PropModeAppend, data, 0)
1490 FROB (XA_CUT_BUFFER0); 1513 FROB (XA_CUT_BUFFER0);
1491 FROB (XA_CUT_BUFFER1); 1514 FROB (XA_CUT_BUFFER1);
1492 FROB (XA_CUT_BUFFER2); 1515 FROB (XA_CUT_BUFFER2);
1561 { 1584 {
1562 struct device *d = decode_x_device (Qnil); 1585 struct device *d = decode_x_device (Qnil);
1563 Display *display = DEVICE_X_DISPLAY (d); 1586 Display *display = DEVICE_X_DISPLAY (d);
1564 Window window = RootWindow (display, 0); /* Cutbuffers are on frame 0 */ 1587 Window window = RootWindow (display, 0); /* Cutbuffers are on frame 0 */
1565 Atom cut_buffer_atom; 1588 Atom cut_buffer_atom;
1566 CONST Extbyte *data = XSTRING_DATA (string); 1589 const Extbyte *data = XSTRING_DATA (string);
1567 Extcount bytes = XSTRING_LENGTH (string); 1590 Extcount bytes = XSTRING_LENGTH (string);
1568 Extcount bytes_remaining; 1591 Extcount bytes_remaining;
1569 int max_bytes = SELECTION_QUANTUM (display); 1592 int max_bytes = SELECTION_QUANTUM (display);
1570 #ifdef MULE 1593 #ifdef MULE
1571 CONST Bufbyte *ptr, *end; 1594 const Bufbyte *ptr, *end;
1572 enum { ASCII, LATIN_1, WORLD } chartypes = ASCII; 1595 enum { ASCII, LATIN_1, WORLD } chartypes = ASCII;
1573 #endif 1596 #endif
1574 1597
1575 if (max_bytes > MAX_SELECTION_QUANTUM) 1598 if (max_bytes > MAX_SELECTION_QUANTUM)
1576 max_bytes = MAX_SELECTION_QUANTUM; 1599 max_bytes = MAX_SELECTION_QUANTUM;
1765 DEVICE_XATOM_INCR (d) = XInternAtom (D, "INCR", False); 1788 DEVICE_XATOM_INCR (d) = XInternAtom (D, "INCR", False);
1766 DEVICE_XATOM_TARGETS (d) = XInternAtom (D, "TARGETS", False); 1789 DEVICE_XATOM_TARGETS (d) = XInternAtom (D, "TARGETS", False);
1767 DEVICE_XATOM_NULL (d) = XInternAtom (D, "NULL", False); 1790 DEVICE_XATOM_NULL (d) = XInternAtom (D, "NULL", False);
1768 DEVICE_XATOM_ATOM_PAIR (d) = XInternAtom (D, "ATOM_PAIR", False); 1791 DEVICE_XATOM_ATOM_PAIR (d) = XInternAtom (D, "ATOM_PAIR", False);
1769 DEVICE_XATOM_COMPOUND_TEXT (d) = XInternAtom (D, "COMPOUND_TEXT", False); 1792 DEVICE_XATOM_COMPOUND_TEXT (d) = XInternAtom (D, "COMPOUND_TEXT", False);
1793
1794 /* #### I don't like the looks of this... what is it for? - ajh */
1770 DEVICE_XATOM_EMACS_TMP (d) = XInternAtom (D, "_EMACS_TMP_", False); 1795 DEVICE_XATOM_EMACS_TMP (d) = XInternAtom (D, "_EMACS_TMP_", False);
1771 } 1796 }