event->kind = NO_EVENT;
}
+static Lisp_Object
+kbd_buffer_get_event_1 (Lisp_Object arg)
+{
+ return code_convert_string (arg, Vlocale_coding_system,
+ Qnil, 0, false, 0);
+}
+
+static Lisp_Object
+kbd_buffer_get_event_2 (Lisp_Object val)
+{
+ return Qnil;
+}
/* Read one event from the event buffer, waiting if necessary.
The value is a Lisp object representing the event.
bool *used_mouse_menu,
struct timespec *end_time)
{
- Lisp_Object obj;
+ Lisp_Object obj, str;
#ifdef subprocesses
if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE / 4)
}
}
+ if (event->kind == MULTIBYTE_CHAR_KEYSTROKE_EVENT
+ /* This string has to be decoded. */
+ && STRINGP (event->ie.arg))
+ {
+ str = internal_condition_case_1 (kbd_buffer_get_event_1,
+ event->ie.arg, Qt,
+ kbd_buffer_get_event_2);
+
+ /* Decoding the string failed, so use the original,
+ where at least ASCII text will work. */
+ if (NILP (str))
+ str = event->ie.arg;
+
+ if (!SCHARS (str))
+ {
+ kbd_fetch_ptr = next_kbd_event (event);
+ obj = Qnil;
+ break;
+ }
+
+ /* car is the index of the next character in the
+ string that will be sent and cdr is the string
+ itself. */
+ event->ie.arg = Fcons (make_fixnum (0), str);
+ }
+
+ if (event->kind == MULTIBYTE_CHAR_KEYSTROKE_EVENT
+ && CONSP (event->ie.arg))
+ {
+ eassert (FIXNUMP (XCAR (event->ie.arg)));
+ eassert (STRINGP (XCDR (event->ie.arg)));
+ eassert (XFIXNUM (XCAR (event->ie.arg))
+ < SCHARS (XCDR (event->ie.arg)));
+
+ event->ie.code = XFIXNUM (Faref (XCDR (event->ie.arg),
+ XCAR (event->ie.arg)));
+
+ XSETCAR (event->ie.arg,
+ make_fixnum (XFIXNUM (XCAR (event->ie.arg)) + 1));
+ }
+
obj = make_lispy_event (&event->ie);
#ifdef HAVE_EXT_MENU_BAR
*used_mouse_menu = true;
#endif
- /* Wipe out this event, to catch bugs. */
- clear_event (&event->ie);
- kbd_fetch_ptr = next_kbd_event (event);
+ if (event->kind != MULTIBYTE_CHAR_KEYSTROKE_EVENT
+ || !CONSP (event->ie.arg)
+ || (XFIXNUM (XCAR (event->ie.arg))
+ >= SCHARS (XCDR (event->ie.arg))))
+ {
+ /* Wipe out this event, to catch bugs. */
+ clear_event (&event->ie);
+ kbd_fetch_ptr = next_kbd_event (event);
+ }
}
}
}
which the key was typed.
.timestamp gives a timestamp (in
milliseconds) for the keystroke. */
- MULTIBYTE_CHAR_KEYSTROKE_EVENT, /* The multibyte char code is in .code,
- perhaps with modifiers applied.
- The others are the same as
- ASCII_KEYSTROKE_EVENT. */
+ MULTIBYTE_CHAR_KEYSTROKE_EVENT, /* The multibyte char code is
+ in .code, perhaps with
+ modifiers applied. The
+ others are the same as
+ ASCII_KEYSTROKE_EVENT,
+ except when ARG is a
+ string, which will be
+ decoded and the decoded
+ string's characters will be
+ used as .code
+ individually. */
NON_ASCII_KEYSTROKE_EVENT, /* .code is a number identifying the
function key. A code N represents
a key whose name is
}
}
+struct x_xim_text_conversion_data
+{
+ struct coding_system *coding;
+ char *source;
+};
+
+static Lisp_Object
+x_xim_text_to_utf8_unix_1 (ptrdiff_t nargs,
+ Lisp_Object *args)
+{
+ struct x_xim_text_conversion_data *data;
+ ptrdiff_t nbytes;
+
+ data = xmint_pointer (args[0]);
+ nbytes = strlen (data->source);
+
+ data->coding->destination = NULL;
+
+ setup_coding_system (Vlocale_coding_system,
+ data->coding);
+ data->coding->mode |= (CODING_MODE_LAST_BLOCK
+ | CODING_MODE_SAFE_ENCODING);
+ data->coding->source = (const unsigned char *) data->source;
+ data->coding->dst_bytes = 2048;
+ data->coding->destination = xmalloc (2048);
+ decode_coding_object (data->coding, Qnil, 0, 0,
+ nbytes, nbytes, Qnil);
+
+ return Qnil;
+}
+
+static Lisp_Object
+x_xim_text_to_utf8_unix_2 (Lisp_Object val,
+ ptrdiff_t nargs,
+ Lisp_Object *args)
+{
+ struct x_xim_text_conversion_data *data;
+
+ data = xmint_pointer (args[0]);
+
+ if (data->coding->destination)
+ xfree (data->coding->destination);
+
+ data->coding->destination = NULL;
+
+ return Qnil;
+}
+
/* The string returned is not null-terminated. */
static char *
x_xim_text_to_utf8_unix (XIMText *text, ptrdiff_t *length)
{
unsigned char *wchar_buf;
ptrdiff_t wchar_actual_length, i;
- ptrdiff_t nbytes;
struct coding_system coding;
+ struct x_xim_text_conversion_data data;
+ bool was_waiting_for_input_p;
+ Lisp_Object arg;
if (text->encoding_is_wchar)
{
return (char *) wchar_buf;
}
- nbytes = strlen (text->string.multi_byte);
- setup_coding_system (Vlocale_coding_system, &coding);
- coding.mode |= (CODING_MODE_LAST_BLOCK
- | CODING_MODE_SAFE_ENCODING);
- coding.source = (const unsigned char *) text->string.multi_byte;
- coding.dst_bytes = 2048;
- coding.destination = xmalloc (2048);
- decode_coding_object (&coding, Qnil, 0, 0, nbytes, nbytes, Qnil);
+ data.coding = &coding;
+ data.source = text->string.multi_byte;
- /* coding.destination has either been allocated by us, or
- reallocated by decode_coding_object. */
+ was_waiting_for_input_p = waiting_for_input;
+ /* Otherwise Fsignal will crash. */
+ waiting_for_input = false;
+ arg = make_mint_ptr (&data);
+ internal_condition_case_n (x_xim_text_to_utf8_unix_1, 1, &arg,
+ Qt, x_xim_text_to_utf8_unix_2);
+ waiting_for_input = was_waiting_for_input_p;
*length = coding.produced;
return (char *) coding.destination;
if (!output->preedit_active)
return;
- /* If we don't bail out here then GTK can crash
- from the resulting signal in `setup_coding_system'. */
- if (NILP (Fcoding_system_p (Vlocale_coding_system)))
+ if (call_data->text)
{
- text = NULL;
- goto im_abort;
- }
+ text = x_xim_text_to_utf8_unix (call_data->text, &text_length);
- if (call_data->text)
- text = x_xim_text_to_utf8_unix (call_data->text, &text_length);
+ if (!text)
+ /* Decoding the IM text failed. */
+ goto im_abort;
+ }
else
text = NULL;
int do_help = 0;
ptrdiff_t nbytes = 0;
struct frame *any, *f = NULL;
- struct coding_system coding;
Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
/* This holds the state XLookupString needs to implement dead keys
and other tricks known as "compose processing". _X Window System_
XEvent configureEvent;
XEvent next_event;
- USE_SAFE_ALLOCA;
-
*finish = X_EVENT_NORMAL;
EVENT_INIT (inev.ie);
unsigned char *copy_bufptr = copy_buffer;
int copy_bufsiz = sizeof (copy_buffer);
int modifiers;
- Lisp_Object coding_system = Qlatin_1;
Lisp_Object c;
/* `xkey' will be modified, but it's not important to modify
`event' itself. */
{
Status status_return;
- coding_system = Vlocale_coding_system;
nbytes = XmbLookupString (FRAME_XIC (f),
&xkey, (char *) copy_bufptr,
copy_bufsiz, &keysym,
{ /* Raw bytes, not keysym. */
ptrdiff_t i;
- int nchars, len;
-
- for (i = 0, nchars = 0; i < nbytes; i++)
- {
- if (ASCII_CHAR_P (copy_bufptr[i]))
- nchars++;
- STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
- }
-
- if (nchars < nbytes)
- {
- /* If we don't bail out here then GTK can crash
- from the resulting signal in `setup_coding_system'. */
- if (NILP (Fcoding_system_p (coding_system)))
- goto done_keysym;
-
- /* Decode the input data. */
-
- /* The input should be decoded with `coding_system'
- which depends on which X*LookupString function
- we used just above and the locale. */
- setup_coding_system (coding_system, &coding);
- coding.src_multibyte = false;
- coding.dst_multibyte = true;
- /* The input is converted to events, thus we can't
- handle composition. Anyway, there's no XIM that
- gives us composition information. */
- coding.common_flags &= ~CODING_ANNOTATION_MASK;
-
- SAFE_NALLOCA (coding.destination, MAX_MULTIBYTE_LENGTH,
- nbytes);
- coding.dst_bytes = MAX_MULTIBYTE_LENGTH * nbytes;
- coding.mode |= CODING_MODE_LAST_BLOCK;
- decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil);
- nbytes = coding.produced;
- nchars = coding.produced_char;
- copy_bufptr = coding.destination;
- }
- /* Convert the input data to a sequence of
- character events. */
- for (i = 0; i < nbytes; i += len)
- {
- int ch;
- if (nchars == nbytes)
- ch = copy_bufptr[i], len = 1;
- else
- ch = string_char_and_length (copy_bufptr + i, &len);
- inev.ie.kind = (SINGLE_BYTE_CHAR_P (ch)
- ? ASCII_KEYSTROKE_EVENT
- : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
- inev.ie.code = ch;
- kbd_buffer_store_buffered_event (&inev, hold_quit);
- }
-
- count += nchars;
+ for (i = 0; i < nbytes; i++)
+ STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
- inev.ie.kind = NO_EVENT; /* Already stored above. */
+ inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+ inev.ie.arg = make_unibyte_string ((char *) copy_bufptr, nbytes);
if (keysym == NoSymbol)
break;
KeySym keysym;
char copy_buffer[81];
char *copy_bufptr = copy_buffer;
- unsigned char *copy_ubufptr;
int copy_bufsiz = sizeof (copy_buffer);
ptrdiff_t i;
- int nchars, len;
struct xi_device_t *device;
device = xi_device_from_id (dpyinfo, xev->deviceid);
goto xi_done_keysym;
}
- for (i = 0, nchars = 0; i < nbytes; i++)
- {
- if (ASCII_CHAR_P (copy_bufptr[i]))
- nchars++;
- STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
- }
+ for (i = 0; i < nbytes; i++)
+ STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]);
- if (nchars < nbytes)
- {
- /* If we don't bail out here then GTK can crash
- from the resulting signal in `setup_coding_system'. */
- if (NILP (Fcoding_system_p (Vlocale_coding_system)))
- goto xi_done_keysym;
-
- /* Decode the input data. */
-
- setup_coding_system (Vlocale_coding_system, &coding);
- coding.src_multibyte = false;
- coding.dst_multibyte = true;
- /* The input is converted to events, thus we can't
- handle composition. Anyway, there's no XIM that
- gives us composition information. */
- coding.common_flags &= ~CODING_ANNOTATION_MASK;
-
- SAFE_NALLOCA (coding.destination, MAX_MULTIBYTE_LENGTH,
- nbytes);
- coding.dst_bytes = MAX_MULTIBYTE_LENGTH * nbytes;
- coding.mode |= CODING_MODE_LAST_BLOCK;
- decode_coding_c_string (&coding, (unsigned char *) copy_bufptr,
- nbytes, Qnil);
- nbytes = coding.produced;
- nchars = coding.produced_char;
- copy_bufptr = (char *) coding.destination;
- }
-
- copy_ubufptr = (unsigned char *) copy_bufptr;
-
- /* Convert the input data to a sequence of
- character events. */
- for (i = 0; i < nbytes; i += len)
- {
- int ch;
- if (nchars == nbytes)
- ch = copy_ubufptr[i], len = 1;
- else
- ch = string_char_and_length (copy_ubufptr + i, &len);
- inev.ie.kind = (SINGLE_BYTE_CHAR_P (ch)
- ? ASCII_KEYSTROKE_EVENT
- : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
- inev.ie.code = ch;
- kbd_buffer_store_buffered_event (&inev, hold_quit);
- }
-
- inev.ie.kind = NO_EVENT;
+ inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+ inev.ie.arg = make_unibyte_string (copy_bufptr, nbytes);
goto xi_done_keysym;
}
+
goto XI_OTHER;
}
/* Sometimes event processing draws to the frame outside redisplay.
To ensure that these changes become visible, draw them here. */
flush_dirty_back_buffers ();
- SAFE_FREE ();
return count;
}