static void hack_motif_clipboard_selection (Atom selection_atom,
Lisp_Object selection_value,
Time thyme, Display *display,
- Window selecting_window);
+ Window selecting_window,
+ int owned_p);
#endif
#define CUT_BUFFER_SUPPORT
/* If the selection owner takes too long to reply to a selection request,
we give up on it. This is in seconds (0 = no timeout).
*/
-int x_selection_timeout;
+Fixnum x_selection_timeout;
+
+/* Enable motif selection optimizations. */
+int x_selection_strict_motif_ownership;
\f
/* Utility functions */
unsigned int *size_ret,
int *format_ret);
static Lisp_Object selection_data_to_lisp_data (struct device *,
- unsigned char *data,
+ Extbyte *data,
size_t size,
Atom type,
int format);
#endif /* CUT_BUFFER_SUPPORT */
{
- CONST char *nameext;
- GET_C_STRING_CTEXT_DATA_ALLOCA (Fsymbol_name (sym), nameext);
+ const char *nameext;
+ LISP_STRING_TO_EXTERNAL (Fsymbol_name (sym), nameext, Qctext);
return XInternAtom (display, nameext, only_if_exists ? True : False);
}
}
#endif
{
- Lisp_Object newsym;
- CONST Bufbyte *intstr;
+ char *intstr;
char *str = XGetAtomName (display, atom);
if (! str) return Qnil;
- GET_C_CHARPTR_INT_CTEXT_DATA_ALLOCA (str, intstr);
- newsym = intern ((char *) intstr);
+ TO_INTERNAL_FORMAT (C_STRING, str,
+ C_STRING_ALLOCA, intstr,
+ Qctext);
XFree (str);
- return newsym;
+ return intern (intstr);
}
}
\f
/* Do protocol to assert ourself as a selection owner.
- Update the Vselection_alist so that we can reply to later requests for
- our selection.
*/
static Lisp_Object
-x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value)
+x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
+ Lisp_Object how_to_add, Lisp_Object selection_type,
+ int owned_p)
{
struct device *d = decode_x_device (Qnil);
Display *display = DEVICE_X_DISPLAY (d);
That assumed equivalence of time_t and Time, which is not
necessarily the case (e.g. under OSF on the Alphas, where
Time is a 64-bit quantity and time_t is a 32-bit quantity).
-
+
Opaque pointers are the clean way to go here.
*/
- selection_time = make_opaque (sizeof (thyme), (void *) &thyme);
+ selection_time = make_opaque (&thyme, sizeof (thyme));
#ifdef MOTIF_CLIPBOARDS
hack_motif_clipboard_selection (selection_atom, selection_value,
- thyme, display, selecting_window);
+ thyme, display, selecting_window, owned_p);
#endif
return selection_time;
}
Lisp_Object selection_value,
Time thyme,
Display *display,
- Window selecting_window)
- /* Bool owned_p)*/
+ Window selecting_window,
+ int owned_p)
{
struct device *d = get_device_from_display (display);
/* Those Motif wankers can't be bothered to follow the ICCCM, and do
to look up the new value, and you can't Copy from a buffer, Paste
into a text field, then Copy something else from the buffer and
paste it into the text field -- it pastes the first thing again. */
-/* && !owned_p */
+ && (!owned_p
+ /* Selectively re-enable this because for most users its
+ just too painful - especially over a remote link. */
+ || x_selection_strict_motif_ownership)
)
{
#ifdef MOTIF_INCREMENTAL_CLIPBOARDS_WORK
#endif
XmString fmh;
String encoding = "STRING";
- CONST Extbyte *data = XSTRING_DATA (selection_value);
- Extcount bytes = XSTRING_LENGTH (selection_value);
+ const Bufbyte *data = XSTRING_DATA (selection_value);
+ Bytecount bytes = XSTRING_LENGTH (selection_value);
#ifdef MULE
{
enum { ASCII, LATIN_1, WORLD } chartypes = ASCII;
- CONST Bufbyte *ptr = data, *end = ptr + bytes;
+ const Bufbyte *ptr = data, *end = ptr + bytes;
/* Optimize for the common ASCII case */
while (ptr <= end)
{
}
if (chartypes == LATIN_1)
- GET_STRING_BINARY_DATA_ALLOCA (selection_value, data, bytes);
+ TO_EXTERNAL_FORMAT (LISP_STRING, selection_value,
+ ALLOCA, (data, bytes),
+ Qbinary);
else if (chartypes == WORLD)
{
- GET_STRING_CTEXT_DATA_ALLOCA (selection_value, data, bytes);
+ TO_EXTERNAL_FORMAT (LISP_STRING, selection_value,
+ ALLOCA, (data, bytes),
+ Qctext);
encoding = "COMPOUND_TEXT";
}
}
{
Display *dpy = XtDisplay (widget);
Window window = (Window) *private_id;
- Lisp_Object selection = assq_no_quit (QCLIPBOARD, Vselection_alist);
- if (NILP (selection)) abort ();
- selection = XCDR (selection);
- if (!STRINGP (selection)) abort ();
+ Lisp_Object selection = select_convert_out (QCLIPBOARD, Qnil, Qnil);
+
+ /* Whichever lazy git wrote this originally just called abort()
+ when anything didn't go their way... */
+
+ /* Try some other text types */
+ if (NILP (selection))
+ selection = select_convert_out (QCLIPBOARD, QSTRING, Qnil);
+ if (NILP (selection))
+ selection = select_convert_out (QCLIPBOARD, QTEXT, Qnil);
+ if (NILP (selection))
+ selection = select_convert_out (QCLIPBOARD, QCOMPOUND_TEXT, Qnil);
+
+ if (CONSP (selection) && SYMBOLP (XCAR (selection))
+ && (EQ (XCAR (selection), QSTRING)
+ || EQ (XCAR (selection), QTEXT)
+ || EQ (XCAR (selection), QCOMPOUND_TEXT)))
+ selection = XCDR (selection);
+
+ if (NILP (selection))
+ signal_error (Qselection_conversion_error,
+ build_string ("no selection"));
+
+ if (!STRINGP (selection))
+ signal_error (Qselection_conversion_error,
+ build_string ("couldn't convert selection to string"));
+
+
XmClipboardCopyByName (dpy, window, *data_id,
(char *) XSTRING_DATA (selection),
XSTRING_LENGTH (selection) + 1,
x_handle_selection_request (XSelectionRequestEvent *event)
{
/* This function can GC */
- struct gcpro gcpro1, gcpro2, gcpro3;
- Lisp_Object local_selection_data = Qnil;
+ struct gcpro gcpro1, gcpro2;
+ Lisp_Object temp_obj;
Lisp_Object selection_symbol;
Lisp_Object target_symbol = Qnil;
Lisp_Object converted_selection = Qnil;
int count;
struct device *d = get_device_from_display (event->display);
- GCPRO3 (local_selection_data, converted_selection, target_symbol);
+ GCPRO2 (converted_selection, target_symbol);
selection_symbol = x_atom_to_symbol (d, event->selection);
+ target_symbol = x_atom_to_symbol (d, event->target);
- local_selection_data = assq_no_quit (selection_symbol, Vselection_alist);
-
-#if 0
- /* This list isn't user-visible, so it can't "go bad." */
- assert (CONSP (local_selection_data));
- assert (CONSP (XCDR (local_selection_data)));
- assert (CONSP (XCDR (XCDR (local_selection_data))));
- assert (NILP (XCDR (XCDR (XCDR (local_selection_data)))));
- assert (CONSP (XCAR (XCDR (XCDR (local_selection_data)))));
- assert (INTP (XCAR (XCAR (XCDR (XCDR (local_selection_data))))));
- assert (INTP (XCDR (XCAR (XCDR (XCDR (local_selection_data))))));
+#if 0 /* #### MULTIPLE doesn't work yet */
+ if (EQ (target_symbol, QMULTIPLE))
+ target_symbol = fetch_multiple_target (event);
#endif
- if (NILP (local_selection_data))
+ temp_obj = Fget_selection_timestamp (selection_symbol);
+
+ if (NILP (temp_obj))
{
- /* Someone asked for the selection, but we don't have it any more. */
+ /* We don't appear to have the selection. */
x_decline_selection_request (event);
+
goto DONE_LABEL;
}
- local_selection_time =
- * (Time *) XOPAQUE_DATA (XCAR (XCDR (XCDR (local_selection_data))));
+ local_selection_time = * (Time *) XOPAQUE_DATA (temp_obj);
if (event->time != CurrentTime &&
local_selection_time > event->time)
goto DONE_LABEL;
}
+ converted_selection = select_convert_out (selection_symbol,
+ target_symbol, Qnil);
+
+ /* #### Is this the right thing to do? I'm no X expert. -- ajh */
+ if (NILP (converted_selection))
+ {
+ /* We don't appear to have a selection in that data type. */
+ x_decline_selection_request (event);
+ goto DONE_LABEL;
+ }
+
count = specpdl_depth ();
record_unwind_protect (x_selection_request_lisp_error,
make_opaque_ptr (event));
- target_symbol = x_atom_to_symbol (d, event->target);
-
-#if 0 /* #### MULTIPLE doesn't work yet */
- if (EQ (target_symbol, QMULTIPLE))
- target_symbol = fetch_multiple_target (event);
-#endif
- /* Convert lisp objects back into binary data */
-
- converted_selection =
- get_local_selection (selection_symbol, target_symbol);
+ {
+ unsigned char *data;
+ unsigned int size;
+ int format;
+ Atom type;
+ lisp_data_to_selection_data (d, converted_selection,
+ &data, &type, &size, &format);
+
+ x_reply_selection_request (event, format, data, size, type);
+ successful_p = Qt;
+ /* Tell x_selection_request_lisp_error() it's cool. */
+ event->type = 0;
+ xfree (data);
+ }
- if (! NILP (converted_selection))
- {
- unsigned char *data;
- unsigned int size;
- int format;
- Atom type;
- lisp_data_to_selection_data (d, converted_selection,
- &data, &type, &size, &format);
-
- x_reply_selection_request (event, format, data, size, type);
- successful_p = Qt;
- /* Tell x_selection_request_lisp_error() it's cool. */ event->type = 0;
- xfree (data);
- }
unbind_to (count, Qnil);
DONE_LABEL:
/* Let random lisp code notice that the selection has been asked for. */
{
- Lisp_Object rest;
Lisp_Object val = Vx_sent_selection_hooks;
if (!UNBOUNDP (val) && !NILP (val))
{
+ Lisp_Object rest;
if (CONSP (val) && !EQ (XCAR (val), Qlambda))
for (rest = val; !NILP (rest); rest = Fcdr (rest))
- call3 (Fcar(rest), selection_symbol, target_symbol,
- successful_p);
+ call3 (Fcar (rest), selection_symbol, target_symbol, successful_p);
else
- call3 (val, selection_symbol, target_symbol,
- successful_p);
+ call3 (val, selection_symbol, target_symbol, successful_p);
}
}
}
Atom selection = event->selection;
Time changed_owner_time = event->time;
- Lisp_Object selection_symbol, local_selection_data;
+ Lisp_Object selection_symbol, local_selection_time_lisp;
Time local_selection_time;
selection_symbol = x_atom_to_symbol (d, selection);
- local_selection_data = assq_no_quit (selection_symbol, Vselection_alist);
+ local_selection_time_lisp = Fget_selection_timestamp (selection_symbol);
- /* Well, we already believe that we don't own it, so that's just fine. */
- if (NILP (local_selection_data)) return;
+ /* We don't own the selection, so that's fine. */
+ if (NILP (local_selection_time_lisp))
+ return;
- local_selection_time =
- * (Time *) XOPAQUE_DATA (XCAR (XCDR (XCDR (local_selection_data))));
+ local_selection_time = * (Time *) XOPAQUE_DATA (local_selection_time_lisp);
/* This SelectionClear is for a selection that we no longer own, so we can
disregard it. (That is, we have reasserted the selection since this
if (changed_owner_time != CurrentTime &&
local_selection_time > changed_owner_time)
return;
-
+
handle_selection_clear (selection_symbol);
}
unbind_to (speccount, Qnil);
/* otherwise, the selection is waiting for us on the requested property. */
- return
- x_get_window_property_as_lisp_data (display, requestor_window,
- target_property, target_type,
- selection_atom);
+
+ return select_convert_in (selection_symbol,
+ target_type,
+ x_get_window_property_as_lisp_data(display,
+ requestor_window,
+ target_property,
+ target_type,
+ selection_atom));
}
static void
x_get_window_property (Display *display, Window window, Atom property,
- unsigned char **data_ret, int *bytes_ret,
+ Extbyte **data_ret, int *bytes_ret,
Atom *actual_type_ret, int *actual_format_ret,
unsigned long *actual_size_ret, int delete_p)
{
- int total_size;
+ size_t total_size;
unsigned long bytes_remaining;
int offset = 0;
unsigned char *tmp_data = 0;
}
total_size = bytes_remaining + 1;
- *data_ret = (unsigned char *) xmalloc (total_size);
+ *data_ret = (Extbyte *) xmalloc (total_size);
/* Now read, until we've gotten it all. */
while (bytes_remaining)
/* this one is for error messages only */
Lisp_Object target_type,
unsigned int min_size_bytes,
- unsigned char **data_ret, int *size_bytes_ret,
+ Extbyte **data_ret, int *size_bytes_ret,
Atom *type_ret, int *format_ret,
unsigned long *size_ret)
{
int offset = 0;
int prop_id;
*size_bytes_ret = min_size_bytes;
- *data_ret = (unsigned char *) xmalloc (*size_bytes_ret);
+ *data_ret = (Extbyte *) xmalloc (*size_bytes_ret);
#if 0
stderr_out ("\nread INCR %d\n", min_size_bytes);
#endif
PropertyNewValue);
while (1)
{
- unsigned char *tmp_data;
+ Extbyte *tmp_data;
int tmp_size_bytes;
wait_for_property_change (prop_id);
/* expect it again immediately, because x_get_window_property may
*size_bytes_ret, offset + tmp_size_bytes);
#endif
*size_bytes_ret = offset + tmp_size_bytes;
- *data_ret = (unsigned char *) xrealloc (*data_ret, *size_bytes_ret);
+ *data_ret = (Extbyte *) xrealloc (*data_ret, *size_bytes_ret);
}
memcpy ((*data_ret) + offset, tmp_data, tmp_size_bytes);
offset += tmp_size_bytes;
Atom actual_type;
int actual_format;
unsigned long actual_size;
- unsigned char *data = NULL;
+ Extbyte *data = NULL;
int bytes = 0;
Lisp_Object val;
struct device *d = get_device_from_display (display);
return val;
}
\f
+/* #### These are going to move into Lisp code(!) with the aid of
+ some new functions I'm working on - ajh */
+
/* These functions convert from the selection data read from the server into
something that we can use from elisp, and vice versa.
static Lisp_Object
selection_data_to_lisp_data (struct device *d,
- unsigned char *data,
+ Extbyte *data,
size_t size,
Atom type,
int format)
return make_ext_string (data, size,
type == DEVICE_XATOM_TEXT (d) ||
type == DEVICE_XATOM_COMPOUND_TEXT (d)
- ? FORMAT_CTEXT : FORMAT_BINARY);
+ ? Qctext : Qbinary);
/* Convert a single atom to a Lisp Symbol.
Convert a set of atoms to a vector of symbols. */
}
else if (STRINGP (obj))
{
- CONST Extbyte *extval;
+ const Extbyte *extval;
Extcount extvallen;
- if (NILP (type))
- GET_STRING_CTEXT_DATA_ALLOCA (obj, extval, extvallen);
- else
- GET_STRING_BINARY_DATA_ALLOCA (obj, extval, extvallen);
+ TO_EXTERNAL_FORMAT (LISP_STRING, obj,
+ ALLOCA, (extval, extvallen),
+ (NILP (type) ? Qctext : Qbinary));
*format_ret = 8;
*size_ret = extvallen;
*data_ret = (unsigned char *) xmalloc (*size_ret);
{
Bufbyte buf[MAX_EMCHAR_LEN];
Bytecount len;
- CONST Extbyte *extval;
+ const Extbyte *extval;
Extcount extvallen;
*format_ret = 8;
len = set_charptr_emchar (buf, XCHAR (obj));
- GET_CHARPTR_EXT_CTEXT_DATA_ALLOCA (buf, len, extval, extvallen);
+ TO_EXTERNAL_FORMAT (DATA, (buf, len),
+ ALLOCA, (extval, extvallen),
+ Qctext);
*size_ret = extvallen;
*data_ret = (unsigned char *) xmalloc (*size_ret);
memcpy (*data_ret, extval, *size_ret);
}
static Lisp_Object
-x_selection_exists_p (Lisp_Object selection)
+x_selection_exists_p (Lisp_Object selection,
+ Lisp_Object selection_type)
{
struct device *d = decode_x_device (Qnil);
Display *dpy = DEVICE_X_DISPLAY (d);
static void
initialize_cut_buffers (Display *display, Window window)
{
- static unsigned CONST char * CONST data = (unsigned CONST char *) "";
+ static unsigned const char * const data = (unsigned const char *) "";
#define FROB(atom) XChangeProperty (display, window, atom, XA_STRING, 8, \
PropModeAppend, data, 0)
FROB (XA_CUT_BUFFER0);
cut_buffers_initialized = 1;
}
-#define CHECK_CUTBUFFER(symbol) \
- { CHECK_SYMBOL (symbol); \
- if (!EQ((symbol),QCUT_BUFFER0) && !EQ((symbol),QCUT_BUFFER1) && \
- !EQ((symbol),QCUT_BUFFER2) && !EQ((symbol),QCUT_BUFFER3) && \
- !EQ((symbol),QCUT_BUFFER4) && !EQ((symbol),QCUT_BUFFER5) && \
- !EQ((symbol),QCUT_BUFFER6) && !EQ((symbol),QCUT_BUFFER7)) \
- signal_error (Qerror, list2 (build_string ("Doesn't name a cutbuffer"), \
- (symbol))); \
- }
+#define CHECK_CUTBUFFER(symbol) do { \
+ CHECK_SYMBOL (symbol); \
+ if (! (EQ (symbol, QCUT_BUFFER0) || \
+ EQ (symbol, QCUT_BUFFER1) || \
+ EQ (symbol, QCUT_BUFFER2) || \
+ EQ (symbol, QCUT_BUFFER3) || \
+ EQ (symbol, QCUT_BUFFER4) || \
+ EQ (symbol, QCUT_BUFFER5) || \
+ EQ (symbol, QCUT_BUFFER6) || \
+ EQ (symbol, QCUT_BUFFER7))) \
+ signal_simple_error ("Doesn't name a cutbuffer", symbol); \
+} while (0)
DEFUN ("x-get-cutbuffer-internal", Fx_get_cutbuffer_internal, 1, 1, 0, /*
Return the value of the named CUTBUFFER (typically CUT_BUFFER0).
Display *display = DEVICE_X_DISPLAY (d);
Window window = RootWindow (display, 0); /* Cutbuffers are on frame 0 */
Atom cut_buffer_atom;
- unsigned char *data;
+ Extbyte *data;
int bytes;
Atom type;
int format;
ret = (bytes ?
make_ext_string (data, bytes,
memchr (data, 0x1b, bytes) ?
- FORMAT_CTEXT : FORMAT_BINARY)
+ Qctext : Qbinary)
: Qnil);
xfree (data);
return ret;
Display *display = DEVICE_X_DISPLAY (d);
Window window = RootWindow (display, 0); /* Cutbuffers are on frame 0 */
Atom cut_buffer_atom;
- CONST Extbyte *data = XSTRING_DATA (string);
- Extcount bytes = XSTRING_LENGTH (string);
- Extcount bytes_remaining;
+ const Bufbyte *data = XSTRING_DATA (string);
+ Bytecount bytes = XSTRING_LENGTH (string);
+ Bytecount bytes_remaining;
int max_bytes = SELECTION_QUANTUM (display);
#ifdef MULE
- CONST Bufbyte *ptr, *end;
+ const Bufbyte *ptr, *end;
enum { ASCII, LATIN_1, WORLD } chartypes = ASCII;
#endif
continue;
}
+#ifdef UTF2000
+ if ((*ptr) <= 0xC3)
+ {
+ chartypes = LATIN_1;
+ ptr += 2;
+ continue;
+ }
+#else
if ((*ptr) == LEADING_BYTE_LATIN_ISO8859_1 ||
(*ptr) == LEADING_BYTE_CONTROL_1)
{
ptr += 2;
continue;
}
+#endif
chartypes = WORLD;
break;
}
if (chartypes == LATIN_1)
- GET_STRING_BINARY_DATA_ALLOCA (string, data, bytes);
+ TO_EXTERNAL_FORMAT (LISP_STRING, string,
+ ALLOCA, (data, bytes),
+ Qbinary);
else if (chartypes == WORLD)
- GET_STRING_CTEXT_DATA_ALLOCA (string, data, bytes);
+ TO_EXTERNAL_FORMAT (LISP_STRING, string,
+ ALLOCA, (data, bytes),
+ Qctext);
#endif /* MULE */
bytes_remaining = bytes;
/************************************************************************/
void
-syms_of_xselect (void)
+syms_of_select_x (void)
{
#ifdef CUT_BUFFER_SUPPORT
}
void
-vars_of_xselect (void)
+reinit_vars_of_select_x (void)
{
-#ifdef CUT_BUFFER_SUPPORT
- cut_buffers_initialized = 0;
- Fprovide (intern ("cut-buffer"));
-#endif
-
reading_selection_reply = 0;
reading_which_selection = 0;
selection_reply_timed_out = 0;
for_whom_the_bell_tolls = 0;
prop_location_tick = 0;
+}
+
+void
+vars_of_select_x (void)
+{
+ reinit_vars_of_select_x ();
+
+#ifdef CUT_BUFFER_SUPPORT
+ cut_buffers_initialized = 0;
+ Fprovide (intern ("cut-buffer"));
+#endif
DEFVAR_LISP ("x-sent-selection-hooks", &Vx_sent_selection_hooks /*
A function or functions to be called after we have responded to some
\"*selectionTimeout\" resource (which is expressed in milliseconds).
*/ );
x_selection_timeout = 0;
+
+ DEFVAR_BOOL ("x-selection-strict-motif-ownership", &x_selection_strict_motif_ownership /*
+*If true and XEmacs already owns the clipboard, don't own it again in the
+Motif way. Owning the selection on the Motif way does a huge amount of
+X protocol, and it makes killing text incredibly slow when using an
+X terminal. However, when enabled Motif text fields don't bother to look up
+the new value, and you can't Copy from a buffer, Paste into a text
+field, then Copy something else from the buffer and paste it into the
+text field; it pastes the first thing again.
+*/ );
+ x_selection_strict_motif_ownership = 1;
}
void
-Xatoms_of_xselect (struct device *d)
+Xatoms_of_select_x (struct device *d)
{
Display *D = DEVICE_X_DISPLAY (d);
DEVICE_XATOM_NULL (d) = XInternAtom (D, "NULL", False);
DEVICE_XATOM_ATOM_PAIR (d) = XInternAtom (D, "ATOM_PAIR", False);
DEVICE_XATOM_COMPOUND_TEXT (d) = XInternAtom (D, "COMPOUND_TEXT", False);
+
+ /* #### I don't like the looks of this... what is it for? - ajh */
DEVICE_XATOM_EMACS_TMP (d) = XInternAtom (D, "_EMACS_TMP_", False);
}