+static Lisp_Object
+read_event_from_main_queue (struct timespec *end_time,
+ sys_jmp_buf local_getcjmp,
+ bool *used_mouse_menu)
+{
+ Lisp_Object c = Qnil;
+ sys_jmp_buf save_jump;
+ KBOARD *kb IF_LINT (= NULL);
+
+ start:
+
+ /* Read from the main queue, and if that gives us something we can't use yet,
+ we put it on the appropriate side queue and try again. */
+
+ if (end_time && timespec_cmp (*end_time, current_timespec ()) <= 0)
+ return c;
+
+ /* Actually read a character, waiting if necessary. */
+ save_getcjmp (save_jump);
+ restore_getcjmp (local_getcjmp);
+ if (!end_time)
+ timer_start_idle ();
+ c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time);
+ restore_getcjmp (save_jump);
+
+ if (! NILP (c) && (kb != current_kboard))
+ {
+ Lisp_Object last = KVAR (kb, kbd_queue);
+ if (CONSP (last))
+ {
+ while (CONSP (XCDR (last)))
+ last = XCDR (last);
+ if (!NILP (XCDR (last)))
+ emacs_abort ();
+ }
+ if (!CONSP (last))
+ kset_kbd_queue (kb, list1 (c));
+ else
+ XSETCDR (last, list1 (c));
+ kb->kbd_queue_has_data = 1;
+ c = Qnil;
+ if (single_kboard)
+ goto start;
+ current_kboard = kb;
+ /* This is going to exit from read_char
+ so we had better get rid of this frame's stuff. */
+ return make_number (-2);
+ }
+
+ /* Terminate Emacs in batch mode if at eof. */
+ if (noninteractive && INTEGERP (c) && XINT (c) < 0)
+ Fkill_emacs (make_number (1));
+
+ if (INTEGERP (c))
+ {
+ /* Add in any extra modifiers, where appropriate. */
+ if ((extra_keyboard_modifiers & CHAR_CTL)
+ || ((extra_keyboard_modifiers & 0177) < ' '
+ && (extra_keyboard_modifiers & 0177) != 0))
+ XSETINT (c, make_ctrl_char (XINT (c)));
+
+ /* Transfer any other modifier bits directly from
+ extra_keyboard_modifiers to c. Ignore the actual character code
+ in the low 16 bits of extra_keyboard_modifiers. */
+ XSETINT (c, XINT (c) | (extra_keyboard_modifiers & ~0xff7f & ~CHAR_CTL));
+ }
+
+ return c;
+}
+
+
+
+/* Like `read_event_from_main_queue' but applies keyboard-coding-system
+ to tty input. */
+static Lisp_Object
+read_decoded_event_from_main_queue (struct timespec *end_time,
+ sys_jmp_buf local_getcjmp,
+ Lisp_Object prev_event,
+ bool *used_mouse_menu)
+{
+#define MAX_ENCODED_BYTES 16
+ Lisp_Object events[MAX_ENCODED_BYTES];
+ int n = 0;
+ while (true)
+ {
+ Lisp_Object nextevt
+ = read_event_from_main_queue (end_time, local_getcjmp,
+ used_mouse_menu);
+#ifdef WINDOWSNT
+ /* w32_console already returns decoded events. It either reads
+ Unicode characters from the Windows keyboard input, or
+ converts characters encoded in the current codepage into
+ Unicode. See w32inevt.c:key_event, near its end. */
+ return nextevt;
+#else
+ struct frame *frame = XFRAME (selected_frame);
+ struct terminal *terminal = frame->terminal;
+ if (!((FRAME_TERMCAP_P (frame) || FRAME_MSDOS_P (frame))
+ /* Don't apply decoding if we're just reading a raw event
+ (e.g. reading bytes sent by the xterm to specify the position
+ of a mouse click). */
+ && (!EQ (prev_event, Qt))
+ && (TERMINAL_KEYBOARD_CODING (terminal)->common_flags
+ & CODING_REQUIRE_DECODING_MASK)))
+ return nextevt; /* No decoding needed. */
+ else
+ {
+ int meta_key = terminal->display_info.tty->meta_key;
+ eassert (n < MAX_ENCODED_BYTES);
+ events[n++] = nextevt;
+ if (NATNUMP (nextevt)
+ && XINT (nextevt) < (meta_key == 1 ? 0x80 : 0x100))
+ { /* An encoded byte sequence, let's try to decode it. */
+ struct coding_system *coding
+ = TERMINAL_KEYBOARD_CODING (terminal);
+ unsigned char *src = alloca (n);
+ int i;
+ for (i = 0; i < n; i++)
+ src[i] = XINT (events[i]);
+ if (meta_key != 2)
+ for (i = 0; i < n; i++)
+ src[i] &= ~0x80;
+ coding->destination = alloca (n * 4);
+ coding->dst_bytes = n * 4;
+ decode_coding_c_string (coding, src, n, Qnil);
+ eassert (coding->produced_char <= n);
+ if (coding->produced_char == 0)
+ { /* The encoded sequence is incomplete. */
+ if (n < MAX_ENCODED_BYTES) /* Avoid buffer overflow. */
+ continue; /* Read on! */
+ }
+ else
+ {
+ const unsigned char *p = coding->destination;
+ eassert (coding->carryover_bytes == 0);
+ n = 0;
+ while (n < coding->produced_char)
+ events[n++] = make_number (STRING_CHAR_ADVANCE (p));
+ }
+ }
+ /* Now `events' should hold decoded events.
+ Normally, n should be equal to 1, but better not rely on it.
+ We can only return one event here, so return the first we
+ had and keep the others (if any) for later. */
+ while (n > 1)
+ Vunread_command_events
+ = Fcons (events[--n], Vunread_command_events);
+ return events[0];
+ }
+#endif
+ }
+}
+