comparison src/select-gtk.c @ 647:b39c14581166

[xemacs-hg @ 2001-08-13 04:45:47 by ben] removal of unsigned, size_t, etc.
author ben
date Mon, 13 Aug 2001 04:46:48 +0000
parents 183866b06e0b
children fdefd0186b75
comparison
equal deleted inserted replaced
646:00c54252fe4f 647:b39c14581166
40 40
41 static Lisp_Object Vretrieved_selection; 41 static Lisp_Object Vretrieved_selection;
42 static gboolean waiting_for_selection; 42 static gboolean waiting_for_selection;
43 Lisp_Object Vgtk_sent_selection_hooks; 43 Lisp_Object Vgtk_sent_selection_hooks;
44 44
45 static Lisp_Object atom_to_symbol (struct device *d, GdkAtom atom); 45 static GdkAtom
46 static GdkAtom symbol_to_gtk_atom (struct device *d, Lisp_Object sym, int only_if_exists); 46 symbol_to_gtk_atom (struct device *d, Lisp_Object sym, int only_if_exists)
47 47 {
48 static void lisp_data_to_selection_data (struct device *, 48 if (NILP (sym)) return GDK_SELECTION_PRIMARY;
49 Lisp_Object obj, 49 if (EQ (sym, Qt)) return GDK_SELECTION_SECONDARY;
50 unsigned char **data_ret, 50 if (EQ (sym, QPRIMARY)) return GDK_SELECTION_PRIMARY;
51 GdkAtom *type_ret, 51 if (EQ (sym, QSECONDARY)) return GDK_SELECTION_SECONDARY;
52 unsigned int *size_ret, 52
53 int *format_ret); 53 {
54 static Lisp_Object selection_data_to_lisp_data (struct device *, 54 const Extbyte *nameext;
55 Extbyte *data, 55 LISP_STRING_TO_EXTERNAL (Fsymbol_name (sym), nameext, Qctext);
56 size_t size, 56 return gdk_atom_intern (nameext, only_if_exists ? TRUE : FALSE);
57 GdkAtom type, 57 }
58 int format); 58 }
59 59
60 static Lisp_Object
61 atom_to_symbol (struct device *d, GdkAtom atom)
62 {
63 if (atom == GDK_SELECTION_PRIMARY) return (QPRIMARY);
64 if (atom == GDK_SELECTION_SECONDARY) return (QSECONDARY);
65
66 {
67 CBufbyte *intstr;
68 Extbyte *str = gdk_atom_name (atom);
69
70 if (! str) return Qnil;
71
72 TO_INTERNAL_FORMAT (C_STRING, str,
73 C_STRING_ALLOCA, intstr,
74 Qctext);
75 g_free (str);
76 return intern (intstr);
77 }
78 }
79
80 #define PROCESSING_GTK_CODE
81 #include "select-common.h"
82 #undef PROCESSING_GTK_CODE
83
84
60 /* Set the selection data to GDK_NONE and NULL data, meaning we were 85 /* Set the selection data to GDK_NONE and NULL data, meaning we were
61 ** unable to do what they wanted. 86 ** unable to do what they wanted.
62 */ 87 */
63 static void 88 static void
64 gtk_decline_selection_request (GtkSelectionData *data) 89 gtk_decline_selection_request (GtkSelectionData *data)
168 193
169 record_unwind_protect (gtk_selection_request_lisp_error, 194 record_unwind_protect (gtk_selection_request_lisp_error,
170 make_opaque_ptr (cl)); 195 make_opaque_ptr (cl));
171 196
172 { 197 {
173 unsigned char *data; 198 UChar_Binary *data;
174 unsigned int size; 199 Memory_Count size;
175 int format; 200 int format;
176 GdkAtom type; 201 GdkAtom type;
177 lisp_data_to_selection_data (d, converted_selection, 202 lisp_data_to_selection_data (d, converted_selection,
178 &data, &type, &size, &format); 203 &data, &type, &size, &format);
179 204
180 gtk_selection_data_set (selection_data, type, format, data, size); 205 gtk_selection_data_set (selection_data, type, format, data,
206 /* #### is this right? */
207 (unsigned int) size);
181 successful_p = Qt; 208 successful_p = Qt;
182 /* Tell x_selection_request_lisp_error() it's cool. */ 209 /* Tell x_selection_request_lisp_error() it's cool. */
183 cl->successful = TRUE; 210 cl->successful = TRUE;
184 xfree (data); 211 xfree (data);
185 } 212 }
304 gtk_get_window_property (struct device *d, GtkWidget *window, GdkAtom property, 331 gtk_get_window_property (struct device *d, GtkWidget *window, GdkAtom property,
305 Extbyte **data_ret, int *bytes_ret, 332 Extbyte **data_ret, int *bytes_ret,
306 GdkAtom *actual_type_ret, int *actual_format_ret, 333 GdkAtom *actual_type_ret, int *actual_format_ret,
307 unsigned long *actual_size_ret, int delete_p) 334 unsigned long *actual_size_ret, int delete_p)
308 { 335 {
309 size_t total_size; 336 /* deleted */
310 unsigned long bytes_remaining;
311 int offset = 0;
312 unsigned char *tmp_data = 0;
313 int result;
314 int buffer_size = SELECTION_QUANTUM (display);
315 if (buffer_size > MAX_SELECTION_QUANTUM) buffer_size = MAX_SELECTION_QUANTUM;
316
317 /* First probe the thing to find out how big it is. */
318 result = XGetWindowProperty (display, window, property,
319 0, 0, False, AnyPropertyType,
320 actual_type_ret, actual_format_ret,
321 actual_size_ret,
322 &bytes_remaining, &tmp_data);
323 if (result != Success)
324 {
325 *data_ret = 0;
326 *bytes_ret = 0;
327 return;
328 }
329 XFree ((char *) tmp_data);
330
331 if (*actual_type_ret == None || *actual_format_ret == 0)
332 {
333 if (delete_p) XDeleteProperty (display, window, property);
334 *data_ret = 0;
335 *bytes_ret = 0;
336 return;
337 }
338
339 total_size = bytes_remaining + 1;
340 *data_ret = (Extbyte *) xmalloc (total_size);
341
342 /* Now read, until we've gotten it all. */
343 while (bytes_remaining)
344 {
345 #if 0
346 int last = bytes_remaining;
347 #endif
348 result =
349 XGetWindowProperty (display, window, property,
350 offset/4, buffer_size/4,
351 (delete_p ? True : False),
352 AnyPropertyType,
353 actual_type_ret, actual_format_ret,
354 actual_size_ret, &bytes_remaining, &tmp_data);
355 #if 0
356 stderr_out ("<< read %d\n", last-bytes_remaining);
357 #endif
358 /* If this doesn't return Success at this point, it means that
359 some clod deleted the selection while we were in the midst of
360 reading it. Deal with that, I guess....
361 */
362 if (result != Success) break;
363 *actual_size_ret *= *actual_format_ret / 8;
364 memcpy ((*data_ret) + offset, tmp_data, *actual_size_ret);
365 offset += *actual_size_ret;
366 XFree ((char *) tmp_data);
367 }
368 *bytes_ret = offset;
369 } 337 }
370 338
371 339
372 static void 340 static void
373 receive_incremental_selection (Display *display, Window window, Atom property, 341 receive_incremental_selection (Display *display, Window window, Atom property,
376 unsigned int min_size_bytes, 344 unsigned int min_size_bytes,
377 Extbyte **data_ret, int *size_bytes_ret, 345 Extbyte **data_ret, int *size_bytes_ret,
378 Atom *type_ret, int *format_ret, 346 Atom *type_ret, int *format_ret,
379 unsigned long *size_ret) 347 unsigned long *size_ret)
380 { 348 {
381 /* This function can GC */ 349 /* deleted */
382 int offset = 0;
383 int prop_id;
384 *size_bytes_ret = min_size_bytes;
385 *data_ret = (Extbyte *) xmalloc (*size_bytes_ret);
386 #if 0
387 stderr_out ("\nread INCR %d\n", min_size_bytes);
388 #endif
389 /* At this point, we have read an INCR property, and deleted it (which
390 is how we ack its receipt: the sending window will be selecting
391 PropertyNotify events on our window to notice this).
392
393 Now, we must loop, waiting for the sending window to put a value on
394 that property, then reading the property, then deleting it to ack.
395 We are done when the sender places a property of length 0.
396 */
397 prop_id = expect_property_change (display, window, property,
398 PropertyNewValue);
399 while (1)
400 {
401 Extbyte *tmp_data;
402 int tmp_size_bytes;
403 wait_for_property_change (prop_id);
404 /* expect it again immediately, because x_get_window_property may
405 .. no it won't, I don't get it.
406 .. Ok, I get it now, the Xt code that implements INCR is broken.
407 */
408 prop_id = expect_property_change (display, window, property,
409 PropertyNewValue);
410 x_get_window_property (display, window, property,
411 &tmp_data, &tmp_size_bytes,
412 type_ret, format_ret, size_ret, 1);
413
414 if (tmp_size_bytes == 0) /* we're done */
415 {
416 #if 0
417 stderr_out (" read INCR done\n");
418 #endif
419 unexpect_property_change (prop_id);
420 if (tmp_data) xfree (tmp_data);
421 break;
422 }
423 #if 0
424 stderr_out (" read INCR %d\n", tmp_size_bytes);
425 #endif
426 if (*size_bytes_ret < offset + tmp_size_bytes)
427 {
428 #if 0
429 stderr_out (" read INCR realloc %d -> %d\n",
430 *size_bytes_ret, offset + tmp_size_bytes);
431 #endif
432 *size_bytes_ret = offset + tmp_size_bytes;
433 *data_ret = (Extbyte *) xrealloc (*data_ret, *size_bytes_ret);
434 }
435 memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes);
436 offset += tmp_size_bytes;
437 xfree (tmp_data);
438 }
439 } 350 }
440 351
441 352
442 static Lisp_Object 353 static Lisp_Object
443 gtk_get_window_property_as_lisp_data (struct device *d, 354 gtk_get_window_property_as_lisp_data (struct device *d,
445 GdkAtom property, 356 GdkAtom property,
446 /* next two for error messages only */ 357 /* next two for error messages only */
447 Lisp_Object target_type, 358 Lisp_Object target_type,
448 GdkAtom selection_atom) 359 GdkAtom selection_atom)
449 { 360 {
450 /* This function can GC */ 361 /* deleted */
451 Atom actual_type;
452 int actual_format;
453 unsigned long actual_size;
454 Extbyte *data = NULL;
455 int bytes = 0;
456 Lisp_Object val;
457 struct device *d = get_device_from_display (display);
458
459 x_get_window_property (display, window, property, &data, &bytes,
460 &actual_type, &actual_format, &actual_size, 1);
461 if (! data)
462 {
463 if (XGetSelectionOwner (display, selection_atom))
464 /* there is a selection owner */
465 signal_error (Qselection_conversion_error,
466 "selection owner couldn't convert",
467 Fcons (Qunbound,
468 Fcons (x_atom_to_symbol (d, selection_atom),
469 actual_type ?
470 list2 (target_type,
471 x_atom_to_symbol (d, actual_type)) :
472 list1 (target_type))));
473 else
474 signal_error (Qselection_conversion_error,
475 "no selection",
476 x_atom_to_symbol (d, selection_atom));
477 }
478
479 if (actual_type == DEVICE_XATOM_INCR (d))
480 {
481 /* Ok, that data wasn't *the* data, it was just the beginning. */
482
483 unsigned int min_size_bytes = * ((unsigned int *) data);
484 xfree (data);
485 receive_incremental_selection (display, window, property, target_type,
486 min_size_bytes, &data, &bytes,
487 &actual_type, &actual_format,
488 &actual_size);
489 }
490
491 /* It's been read. Now convert it to a lisp object in some semi-rational
492 manner. */
493 val = selection_data_to_lisp_data (d, data, bytes,
494 actual_type, actual_format);
495
496 xfree (data);
497 return val;
498 } 362 }
499 #endif 363 #endif
500
501
502 static GdkAtom
503 symbol_to_gtk_atom (struct device *d, Lisp_Object sym, int only_if_exists)
504 {
505 if (NILP (sym)) return GDK_SELECTION_PRIMARY;
506 if (EQ (sym, Qt)) return GDK_SELECTION_SECONDARY;
507 if (EQ (sym, QPRIMARY)) return GDK_SELECTION_PRIMARY;
508 if (EQ (sym, QSECONDARY)) return GDK_SELECTION_SECONDARY;
509
510 {
511 const char *nameext;
512 LISP_STRING_TO_EXTERNAL (Fsymbol_name (sym), nameext, Qctext);
513 return gdk_atom_intern (nameext, only_if_exists ? TRUE : FALSE);
514 }
515 }
516
517 static Lisp_Object
518 atom_to_symbol (struct device *d, GdkAtom atom)
519 {
520 if (atom == GDK_SELECTION_PRIMARY) return (QPRIMARY);
521 if (atom == GDK_SELECTION_SECONDARY) return (QSECONDARY);
522
523 {
524 char *intstr;
525 char *str = gdk_atom_name (atom);
526
527 if (! str) return Qnil;
528
529 TO_INTERNAL_FORMAT (C_STRING, str,
530 C_STRING_ALLOCA, intstr,
531 Qctext);
532 g_free (str);
533 return intern (intstr);
534 }
535 }
536
537 /* #### These are going to move into Lisp code(!) with the aid of
538 some new functions I'm working on - ajh */
539
540 /* These functions convert from the selection data read from the server into
541 something that we can use from elisp, and vice versa.
542
543 Type: Format: Size: Elisp Type:
544 ----- ------- ----- -----------
545 * 8 * String
546 ATOM 32 1 Symbol
547 ATOM 32 > 1 Vector of Symbols
548 * 16 1 Integer
549 * 16 > 1 Vector of Integers
550 * 32 1 if <=16 bits: Integer
551 if > 16 bits: Cons of top16, bot16
552 * 32 > 1 Vector of the above
553
554 When converting a Lisp number to C, it is assumed to be of format 16 if
555 it is an integer, and of format 32 if it is a cons of two integers.
556
557 When converting a vector of numbers from Elisp to C, it is assumed to be
558 of format 16 if every element in the vector is an integer, and is assumed
559 to be of format 32 if any element is a cons of two integers.
560
561 When converting an object to C, it may be of the form (SYMBOL . <data>)
562 where SYMBOL is what we should claim that the type is. Format and
563 representation are as above.
564
565 NOTE: Under Mule, when someone shoves us a string without a type, we
566 set the type to 'COMPOUND_TEXT and automatically convert to Compound
567 Text. If the string has a type, we assume that the user wants the
568 data sent as-is so we just do "binary" conversion.
569 */
570
571
572 static Lisp_Object
573 selection_data_to_lisp_data (struct device *d,
574 Extbyte *data,
575 size_t size,
576 GdkAtom type,
577 int format)
578 {
579 if (type == gdk_atom_intern ("NULL", 0))
580 return QNULL;
581
582 /* Convert any 8-bit data to a string, for compactness. */
583 else if (format == 8)
584 return make_ext_string (data, size,
585 ((type == gdk_atom_intern ("TEXT", FALSE)) ||
586 (type == gdk_atom_intern ("COMPOUND_TEXT", FALSE)))
587 ? Qctext : Qbinary);
588
589 /* Convert a single atom to a Lisp Symbol.
590 Convert a set of atoms to a vector of symbols. */
591 else if (type == gdk_atom_intern ("ATOM", FALSE))
592 {
593 if (size == sizeof (GdkAtom))
594 return atom_to_symbol (d, *((GdkAtom *) data));
595 else
596 {
597 int i;
598 int len = size / sizeof (GdkAtom);
599 Lisp_Object v = Fmake_vector (make_int (len), Qzero);
600 for (i = 0; i < len; i++)
601 Faset (v, make_int (i), atom_to_symbol (d, ((GdkAtom *) data) [i]));
602 return v;
603 }
604 }
605
606 /* Convert a single 16 or small 32 bit number to a Lisp Int.
607 If the number is > 16 bits, convert it to a cons of integers,
608 16 bits in each half.
609 */
610 else if (format == 32 && size == sizeof (long))
611 return word_to_lisp (((unsigned long *) data) [0]);
612 else if (format == 16 && size == sizeof (short))
613 return make_int ((int) (((unsigned short *) data) [0]));
614
615 /* Convert any other kind of data to a vector of numbers, represented
616 as above (as an integer, or a cons of two 16 bit integers).
617
618 #### Perhaps we should return the actual type to lisp as well.
619
620 (x-get-selection-internal 'PRIMARY 'LINE_NUMBER)
621 ==> [4 4]
622
623 and perhaps it should be
624
625 (x-get-selection-internal 'PRIMARY 'LINE_NUMBER)
626 ==> (SPAN . [4 4])
627
628 Right now the fact that the return type was SPAN is discarded before
629 lisp code gets to see it.
630 */
631 else if (format == 16)
632 {
633 int i;
634 Lisp_Object v = make_vector (size / 4, Qzero);
635 for (i = 0; i < (int) size / 4; i++)
636 {
637 int j = (int) ((unsigned short *) data) [i];
638 Faset (v, make_int (i), make_int (j));
639 }
640 return v;
641 }
642 else
643 {
644 int i;
645 Lisp_Object v = make_vector (size / 4, Qzero);
646 for (i = 0; i < (int) size / 4; i++)
647 {
648 unsigned long j = ((unsigned long *) data) [i];
649 Faset (v, make_int (i), word_to_lisp (j));
650 }
651 return v;
652 }
653 }
654
655
656 static void
657 lisp_data_to_selection_data (struct device *d,
658 Lisp_Object obj,
659 unsigned char **data_ret,
660 GdkAtom *type_ret,
661 unsigned int *size_ret,
662 int *format_ret)
663 {
664 Lisp_Object type = Qnil;
665
666 if (CONSP (obj) && SYMBOLP (XCAR (obj)))
667 {
668 type = XCAR (obj);
669 obj = XCDR (obj);
670 if (CONSP (obj) && NILP (XCDR (obj)))
671 obj = XCAR (obj);
672 }
673
674 if (EQ (obj, QNULL) || (EQ (type, QNULL)))
675 { /* This is not the same as declining */
676 *format_ret = 32;
677 *size_ret = 0;
678 *data_ret = 0;
679 type = QNULL;
680 }
681 else if (STRINGP (obj))
682 {
683 const Extbyte *extval;
684 Extcount extvallen;
685
686 TO_EXTERNAL_FORMAT (LISP_STRING, obj,
687 ALLOCA, (extval, extvallen),
688 (NILP (type) ? Qctext : Qbinary));
689 *format_ret = 8;
690 *size_ret = extvallen;
691 *data_ret = (unsigned char *) xmalloc (*size_ret);
692 memcpy (*data_ret, extval, *size_ret);
693 #ifdef MULE
694 if (NILP (type)) type = QCOMPOUND_TEXT;
695 #else
696 if (NILP (type)) type = QSTRING;
697 #endif
698 }
699 else if (CHARP (obj))
700 {
701 Bufbyte buf[MAX_EMCHAR_LEN];
702 Bytecount len;
703 const Extbyte *extval;
704 Extcount extvallen;
705
706 *format_ret = 8;
707 len = set_charptr_emchar (buf, XCHAR (obj));
708 TO_EXTERNAL_FORMAT (DATA, (buf, len),
709 ALLOCA, (extval, extvallen),
710 Qctext);
711 *size_ret = extvallen;
712 *data_ret = (unsigned char *) xmalloc (*size_ret);
713 memcpy (*data_ret, extval, *size_ret);
714 #ifdef MULE
715 if (NILP (type)) type = QCOMPOUND_TEXT;
716 #else
717 if (NILP (type)) type = QSTRING;
718 #endif
719 }
720 else if (SYMBOLP (obj))
721 {
722 *format_ret = 32;
723 *size_ret = 1;
724 *data_ret = (unsigned char *) xmalloc (sizeof (GdkAtom) + 1);
725 (*data_ret) [sizeof (GdkAtom)] = 0;
726 (*(GdkAtom **) data_ret) [0] = symbol_to_gtk_atom (d, obj, 0);
727 if (NILP (type)) type = QATOM;
728 }
729 else if (INTP (obj) &&
730 XINT (obj) <= 0x7FFF &&
731 XINT (obj) >= -0x8000)
732 {
733 *format_ret = 16;
734 *size_ret = 1;
735 *data_ret = (unsigned char *) xmalloc (sizeof (short) + 1);
736 (*data_ret) [sizeof (short)] = 0;
737 (*(short **) data_ret) [0] = (short) XINT (obj);
738 if (NILP (type)) type = QINTEGER;
739 }
740 else if (INTP (obj) || CONSP (obj))
741 {
742 *format_ret = 32;
743 *size_ret = 1;
744 *data_ret = (unsigned char *) xmalloc (sizeof (long) + 1);
745 (*data_ret) [sizeof (long)] = 0;
746 (*(unsigned long **) data_ret) [0] = lisp_to_word (obj);
747 if (NILP (type)) type = QINTEGER;
748 }
749 else if (VECTORP (obj))
750 {
751 /* Lisp Vectors may represent a set of ATOMs;
752 a set of 16 or 32 bit INTEGERs;
753 or a set of ATOM_PAIRs (represented as [[A1 A2] [A3 A4] ...]
754 */
755 int i;
756
757 if (SYMBOLP (XVECTOR_DATA (obj) [0]))
758 /* This vector is an ATOM set */
759 {
760 if (NILP (type)) type = QATOM;
761 *size_ret = XVECTOR_LENGTH (obj);
762 *format_ret = 32;
763 *data_ret = (unsigned char *) xmalloc ((*size_ret) * sizeof (GdkAtom));
764 for (i = 0; i < (int) (*size_ret); i++)
765 if (SYMBOLP (XVECTOR_DATA (obj) [i]))
766 (*(GdkAtom **) data_ret) [i] =
767 symbol_to_gtk_atom (d, XVECTOR_DATA (obj) [i], 0);
768 else
769 syntax_error
770 ("all elements of the vector must be of the same type", obj);
771 }
772 #if 0 /* #### MULTIPLE doesn't work yet */
773 else if (VECTORP (XVECTOR_DATA (obj) [0]))
774 /* This vector is an ATOM_PAIR set */
775 {
776 if (NILP (type)) type = QATOM_PAIR;
777 *size_ret = XVECTOR_LENGTH (obj);
778 *format_ret = 32;
779 *data_ret = (unsigned char *)
780 xmalloc ((*size_ret) * sizeof (Atom) * 2);
781 for (i = 0; i < *size_ret; i++)
782 if (VECTORP (XVECTOR_DATA (obj) [i]))
783 {
784 Lisp_Object pair = XVECTOR_DATA (obj) [i];
785 if (XVECTOR_LENGTH (pair) != 2)
786 syntax_error
787 ("elements of the vector must be vectors of exactly two elements", pair);
788
789 (*(GdkAtom **) data_ret) [i * 2] =
790 symbol_to_gtk_atom (d, XVECTOR_DATA (pair) [0], 0);
791 (*(GdkAtom **) data_ret) [(i * 2) + 1] =
792 symbol_to_gtk_atom (d, XVECTOR_DATA (pair) [1], 0);
793 }
794 else
795 syntax_error
796 ("all elements of the vector must be of the same type", obj);
797 }
798 #endif
799 else
800 /* This vector is an INTEGER set, or something like it */
801 {
802 *size_ret = XVECTOR_LENGTH (obj);
803 if (NILP (type)) type = QINTEGER;
804 *format_ret = 16;
805 for (i = 0; i < (int) (*size_ret); i++)
806 if (CONSP (XVECTOR_DATA (obj) [i]))
807 *format_ret = 32;
808 else if (!INTP (XVECTOR_DATA (obj) [i]))
809 syntax_error
810 ("all elements of the vector must be integers or conses of integers", obj);
811
812 *data_ret = (unsigned char *) xmalloc (*size_ret * (*format_ret/8));
813 for (i = 0; i < (int) (*size_ret); i++)
814 if (*format_ret == 32)
815 (*((unsigned long **) data_ret)) [i] =
816 lisp_to_word (XVECTOR_DATA (obj) [i]);
817 else
818 (*((unsigned short **) data_ret)) [i] =
819 (unsigned short) lisp_to_word (XVECTOR_DATA (obj) [i]);
820 }
821 }
822 else
823 invalid_argument ("unrecognized selection data", obj);
824
825 *type_ret = symbol_to_gtk_atom (d, type, 0);
826 }
827 364
828 365
829 366
830 static Lisp_Object 367 static Lisp_Object
831 gtk_own_selection (Lisp_Object selection_name, Lisp_Object selection_value, 368 gtk_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,