diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/xterm.c | 807 |
1 files changed, 322 insertions, 485 deletions
diff --git a/src/xterm.c b/src/xterm.c index 26fb7aa3684..0f1faeafbbd 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -336,16 +336,10 @@ static void x_clear_frame P_ ((void)); | |||
| 336 | static void frame_highlight P_ ((struct frame *)); | 336 | static void frame_highlight P_ ((struct frame *)); |
| 337 | static void frame_unhighlight P_ ((struct frame *)); | 337 | static void frame_unhighlight P_ ((struct frame *)); |
| 338 | static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *)); | 338 | static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *)); |
| 339 | static int x_focus_changed P_ ((int, | 339 | static void x_focus_changed P_ ((int, int, struct x_display_info *, |
| 340 | int, | 340 | struct frame *, struct input_event *)); |
| 341 | struct x_display_info *, | 341 | static void x_detect_focus_change P_ ((struct x_display_info *, |
| 342 | struct frame *, | 342 | XEvent *, struct input_event *)); |
| 343 | struct input_event *, | ||
| 344 | int)); | ||
| 345 | static int x_detect_focus_change P_ ((struct x_display_info *, | ||
| 346 | XEvent *, | ||
| 347 | struct input_event *, | ||
| 348 | int)); | ||
| 349 | static void XTframe_rehighlight P_ ((struct frame *)); | 343 | static void XTframe_rehighlight P_ ((struct frame *)); |
| 350 | static void x_frame_rehighlight P_ ((struct x_display_info *)); | 344 | static void x_frame_rehighlight P_ ((struct x_display_info *)); |
| 351 | static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *)); | 345 | static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *)); |
| @@ -364,11 +358,8 @@ static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *, | |||
| 364 | unsigned long *)); | 358 | unsigned long *)); |
| 365 | static void x_check_fullscreen P_ ((struct frame *)); | 359 | static void x_check_fullscreen P_ ((struct frame *)); |
| 366 | static void x_check_expected_move P_ ((struct frame *)); | 360 | static void x_check_expected_move P_ ((struct frame *)); |
| 367 | static int handle_one_xevent P_ ((struct x_display_info *, | 361 | static int handle_one_xevent P_ ((struct x_display_info *, XEvent *, |
| 368 | XEvent *, | 362 | int *, struct input_event *)); |
| 369 | struct input_event **, | ||
| 370 | int *, | ||
| 371 | int *)); | ||
| 372 | 363 | ||
| 373 | 364 | ||
| 374 | /* Flush display of frame F, or of all frames if F is null. */ | 365 | /* Flush display of frame F, or of all frames if F is null. */ |
| @@ -3167,20 +3158,16 @@ x_new_focus_frame (dpyinfo, frame) | |||
| 3167 | 3158 | ||
| 3168 | /* Handle FocusIn and FocusOut state changes for FRAME. | 3159 | /* Handle FocusIn and FocusOut state changes for FRAME. |
| 3169 | If FRAME has focus and there exists more than one frame, puts | 3160 | If FRAME has focus and there exists more than one frame, puts |
| 3170 | a FOCUS_IN_EVENT into BUFP. | 3161 | a FOCUS_IN_EVENT into *BUFP. */ |
| 3171 | Returns number of events inserted into BUFP. */ | ||
| 3172 | 3162 | ||
| 3173 | static int | 3163 | static void |
| 3174 | x_focus_changed (type, state, dpyinfo, frame, bufp, numchars) | 3164 | x_focus_changed (type, state, dpyinfo, frame, bufp) |
| 3175 | int type; | 3165 | int type; |
| 3176 | int state; | 3166 | int state; |
| 3177 | struct x_display_info *dpyinfo; | 3167 | struct x_display_info *dpyinfo; |
| 3178 | struct frame *frame; | 3168 | struct frame *frame; |
| 3179 | struct input_event *bufp; | 3169 | struct input_event *bufp; |
| 3180 | int numchars; | ||
| 3181 | { | 3170 | { |
| 3182 | int nr_events = 0; | ||
| 3183 | |||
| 3184 | if (type == FocusIn) | 3171 | if (type == FocusIn) |
| 3185 | { | 3172 | { |
| 3186 | if (dpyinfo->x_focus_event_frame != frame) | 3173 | if (dpyinfo->x_focus_event_frame != frame) |
| @@ -3190,17 +3177,12 @@ x_focus_changed (type, state, dpyinfo, frame, bufp, numchars) | |||
| 3190 | 3177 | ||
| 3191 | /* Don't stop displaying the initial startup message | 3178 | /* Don't stop displaying the initial startup message |
| 3192 | for a switch-frame event we don't need. */ | 3179 | for a switch-frame event we don't need. */ |
| 3193 | if (numchars > 0 | 3180 | if (GC_NILP (Vterminal_frame) |
| 3194 | && GC_NILP (Vterminal_frame) | ||
| 3195 | && GC_CONSP (Vframe_list) | 3181 | && GC_CONSP (Vframe_list) |
| 3196 | && !GC_NILP (XCDR (Vframe_list))) | 3182 | && !GC_NILP (XCDR (Vframe_list))) |
| 3197 | { | 3183 | { |
| 3198 | bufp->kind = FOCUS_IN_EVENT; | 3184 | bufp->kind = FOCUS_IN_EVENT; |
| 3199 | XSETFRAME (bufp->frame_or_window, frame); | 3185 | XSETFRAME (bufp->frame_or_window, frame); |
| 3200 | bufp->arg = Qnil; | ||
| 3201 | ++bufp; | ||
| 3202 | numchars--; | ||
| 3203 | ++nr_events; | ||
| 3204 | } | 3186 | } |
| 3205 | } | 3187 | } |
| 3206 | 3188 | ||
| @@ -3226,27 +3208,25 @@ x_focus_changed (type, state, dpyinfo, frame, bufp, numchars) | |||
| 3226 | XUnsetICFocus (FRAME_XIC (frame)); | 3208 | XUnsetICFocus (FRAME_XIC (frame)); |
| 3227 | #endif | 3209 | #endif |
| 3228 | } | 3210 | } |
| 3229 | |||
| 3230 | return nr_events; | ||
| 3231 | } | 3211 | } |
| 3232 | 3212 | ||
| 3233 | /* The focus may have changed. Figure out if it is a real focus change, | 3213 | /* The focus may have changed. Figure out if it is a real focus change, |
| 3234 | by checking both FocusIn/Out and Enter/LeaveNotify events. | 3214 | by checking both FocusIn/Out and Enter/LeaveNotify events. |
| 3235 | 3215 | ||
| 3236 | Returns number of events inserted into BUFP. */ | 3216 | Returns FOCUS_IN_EVENT event in *BUFP. */ |
| 3237 | 3217 | ||
| 3238 | static int | 3218 | static void |
| 3239 | x_detect_focus_change (dpyinfo, event, bufp, numchars) | 3219 | x_detect_focus_change (dpyinfo, event, bufp) |
| 3240 | struct x_display_info *dpyinfo; | 3220 | struct x_display_info *dpyinfo; |
| 3241 | XEvent *event; | 3221 | XEvent *event; |
| 3242 | struct input_event *bufp; | 3222 | struct input_event *bufp; |
| 3243 | int numchars; | ||
| 3244 | { | 3223 | { |
| 3245 | struct frame *frame; | 3224 | struct frame *frame; |
| 3246 | int nr_events = 0; | 3225 | int nr_events = 0; |
| 3247 | 3226 | ||
| 3248 | frame = x_any_window_to_frame (dpyinfo, event->xany.window); | 3227 | frame = x_any_window_to_frame (dpyinfo, event->xany.window); |
| 3249 | if (! frame) return nr_events; | 3228 | if (! frame) |
| 3229 | return; | ||
| 3250 | 3230 | ||
| 3251 | switch (event->type) | 3231 | switch (event->type) |
| 3252 | { | 3232 | { |
| @@ -3260,29 +3240,20 @@ x_detect_focus_change (dpyinfo, event, bufp, numchars) | |||
| 3260 | if (event->xcrossing.detail != NotifyInferior | 3240 | if (event->xcrossing.detail != NotifyInferior |
| 3261 | && event->xcrossing.focus | 3241 | && event->xcrossing.focus |
| 3262 | && ! (focus_state & FOCUS_EXPLICIT)) | 3242 | && ! (focus_state & FOCUS_EXPLICIT)) |
| 3263 | nr_events = x_focus_changed ((event->type == EnterNotify | 3243 | x_focus_changed ((event->type == EnterNotify ? FocusIn : FocusOut), |
| 3264 | ? FocusIn : FocusOut), | 3244 | FOCUS_IMPLICIT, |
| 3265 | FOCUS_IMPLICIT, | 3245 | dpyinfo, frame, bufp); |
| 3266 | dpyinfo, | ||
| 3267 | frame, | ||
| 3268 | bufp, | ||
| 3269 | numchars); | ||
| 3270 | } | 3246 | } |
| 3271 | break; | 3247 | break; |
| 3272 | 3248 | ||
| 3273 | case FocusIn: | 3249 | case FocusIn: |
| 3274 | case FocusOut: | 3250 | case FocusOut: |
| 3275 | nr_events = x_focus_changed (event->type, | 3251 | x_focus_changed (event->type, |
| 3276 | (event->xfocus.detail == NotifyPointer | 3252 | (event->xfocus.detail == NotifyPointer ? |
| 3277 | ? FOCUS_IMPLICIT : FOCUS_EXPLICIT), | 3253 | FOCUS_IMPLICIT : FOCUS_EXPLICIT), |
| 3278 | dpyinfo, | 3254 | dpyinfo, frame, bufp); |
| 3279 | frame, | ||
| 3280 | bufp, | ||
| 3281 | numchars); | ||
| 3282 | break; | 3255 | break; |
| 3283 | } | 3256 | } |
| 3284 | |||
| 3285 | return nr_events; | ||
| 3286 | } | 3257 | } |
| 3287 | 3258 | ||
| 3288 | 3259 | ||
| @@ -3627,35 +3598,39 @@ glyph_rect (f, x, y, rect) | |||
| 3627 | XRectangle *rect; | 3598 | XRectangle *rect; |
| 3628 | { | 3599 | { |
| 3629 | Lisp_Object window; | 3600 | Lisp_Object window; |
| 3630 | int found = 0; | 3601 | struct window *w; |
| 3602 | struct glyph_row *r, *end_row; | ||
| 3631 | 3603 | ||
| 3632 | window = window_from_coordinates (f, x, y, 0, &x, &y, 0); | 3604 | window = window_from_coordinates (f, x, y, 0, &x, &y, 0); |
| 3633 | if (!NILP (window)) | 3605 | if (NILP (window)) |
| 3634 | { | 3606 | return 0; |
| 3635 | struct window *w = XWINDOW (window); | ||
| 3636 | struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); | ||
| 3637 | struct glyph_row *end = r + w->current_matrix->nrows - 1; | ||
| 3638 | 3607 | ||
| 3639 | for (; !found && r < end && r->enabled_p; ++r) | 3608 | w = XWINDOW (window); |
| 3640 | if (r->y >= y) | 3609 | r = MATRIX_FIRST_TEXT_ROW (w->current_matrix); |
| 3641 | { | 3610 | end_row = r + w->current_matrix->nrows - 1; |
| 3642 | struct glyph *g = r->glyphs[TEXT_AREA]; | ||
| 3643 | struct glyph *end = g + r->used[TEXT_AREA]; | ||
| 3644 | int gx; | ||
| 3645 | 3611 | ||
| 3646 | for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g) | 3612 | for (; r < end_row && r->enabled_p; ++r) |
| 3647 | if (gx >= x) | 3613 | { |
| 3648 | { | 3614 | if (r->y >= y) |
| 3649 | rect->width = g->pixel_width; | 3615 | { |
| 3650 | rect->height = r->height; | 3616 | struct glyph *g = r->glyphs[TEXT_AREA]; |
| 3651 | rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx); | 3617 | struct glyph *end = g + r->used[TEXT_AREA]; |
| 3652 | rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y); | 3618 | int gx = r->x; |
| 3653 | found = 1; | 3619 | while (g < end && gx < x) |
| 3654 | } | 3620 | gx += g->pixel_width, ++g; |
| 3655 | } | 3621 | if (g < end) |
| 3622 | { | ||
| 3623 | rect->width = g->pixel_width; | ||
| 3624 | rect->height = r->height; | ||
| 3625 | rect->x = WINDOW_TO_FRAME_PIXEL_X (w, gx); | ||
| 3626 | rect->y = WINDOW_TO_FRAME_PIXEL_Y (w, r->y); | ||
| 3627 | return 1; | ||
| 3628 | } | ||
| 3629 | break; | ||
| 3630 | } | ||
| 3656 | } | 3631 | } |
| 3657 | 3632 | ||
| 3658 | return found; | 3633 | return 0; |
| 3659 | } | 3634 | } |
| 3660 | 3635 | ||
| 3661 | 3636 | ||
| @@ -5648,6 +5623,11 @@ static XComposeStatus compose_status; | |||
| 5648 | static int temp_index; | 5623 | static int temp_index; |
| 5649 | static short temp_buffer[100]; | 5624 | static short temp_buffer[100]; |
| 5650 | 5625 | ||
| 5626 | #define STORE_KEYSYM_FOR_DEBUG(keysym) \ | ||
| 5627 | if (temp_index == sizeof temp_buffer / sizeof (short)) \ | ||
| 5628 | temp_index = 0; \ | ||
| 5629 | temp_buffer[temp_index++] = (keysym) | ||
| 5630 | |||
| 5651 | /* Set this to nonzero to fake an "X I/O error" | 5631 | /* Set this to nonzero to fake an "X I/O error" |
| 5652 | on a particular display. */ | 5632 | on a particular display. */ |
| 5653 | 5633 | ||
| @@ -5667,15 +5647,8 @@ static struct x_display_info *next_noop_dpyinfo; | |||
| 5667 | f->output_data.x->saved_menu_event \ | 5647 | f->output_data.x->saved_menu_event \ |
| 5668 | = (XEvent *) xmalloc (sizeof (XEvent)); \ | 5648 | = (XEvent *) xmalloc (sizeof (XEvent)); \ |
| 5669 | bcopy (&event, f->output_data.x->saved_menu_event, size); \ | 5649 | bcopy (&event, f->output_data.x->saved_menu_event, size); \ |
| 5670 | if (numchars >= 1) \ | 5650 | inev.kind = MENU_BAR_ACTIVATE_EVENT; \ |
| 5671 | { \ | 5651 | XSETFRAME (inev.frame_or_window, f); \ |
| 5672 | bufp->kind = MENU_BAR_ACTIVATE_EVENT; \ | ||
| 5673 | XSETFRAME (bufp->frame_or_window, f); \ | ||
| 5674 | bufp->arg = Qnil; \ | ||
| 5675 | bufp++; \ | ||
| 5676 | count++; \ | ||
| 5677 | numchars--; \ | ||
| 5678 | } \ | ||
| 5679 | } \ | 5652 | } \ |
| 5680 | while (0) | 5653 | while (0) |
| 5681 | 5654 | ||
| @@ -5717,14 +5690,13 @@ x_filter_event (dpyinfo, event) | |||
| 5717 | #endif | 5690 | #endif |
| 5718 | 5691 | ||
| 5719 | #ifdef USE_GTK | 5692 | #ifdef USE_GTK |
| 5720 | static struct input_event **current_bufp; | ||
| 5721 | static int *current_numcharsp; | ||
| 5722 | static int current_count; | 5693 | static int current_count; |
| 5723 | static int current_finish; | 5694 | static int current_finish; |
| 5695 | static struct input_event *current_hold_quit; | ||
| 5724 | 5696 | ||
| 5725 | /* This is the filter function invoked by the GTK event loop. | 5697 | /* This is the filter function invoked by the GTK event loop. |
| 5726 | It is invoked before the XEvent is translated to a GdkEvent, | 5698 | It is invoked before the XEvent is translated to a GdkEvent, |
| 5727 | so we have a chanse to act on the event before GTK. */ | 5699 | so we have a chance to act on the event before GTK. */ |
| 5728 | static GdkFilterReturn | 5700 | static GdkFilterReturn |
| 5729 | event_handler_gdk (gxev, ev, data) | 5701 | event_handler_gdk (gxev, ev, data) |
| 5730 | GdkXEvent *gxev; | 5702 | GdkXEvent *gxev; |
| @@ -5733,7 +5705,7 @@ event_handler_gdk (gxev, ev, data) | |||
| 5733 | { | 5705 | { |
| 5734 | XEvent *xev = (XEvent *) gxev; | 5706 | XEvent *xev = (XEvent *) gxev; |
| 5735 | 5707 | ||
| 5736 | if (current_numcharsp) | 5708 | if (current_count >= 0) |
| 5737 | { | 5709 | { |
| 5738 | struct x_display_info *dpyinfo; | 5710 | struct x_display_info *dpyinfo; |
| 5739 | 5711 | ||
| @@ -5751,11 +5723,11 @@ event_handler_gdk (gxev, ev, data) | |||
| 5751 | if (! dpyinfo) | 5723 | if (! dpyinfo) |
| 5752 | current_finish = X_EVENT_NORMAL; | 5724 | current_finish = X_EVENT_NORMAL; |
| 5753 | else | 5725 | else |
| 5754 | current_count += handle_one_xevent (dpyinfo, | 5726 | { |
| 5755 | xev, | 5727 | current_count += |
| 5756 | current_bufp, | 5728 | handle_one_xevent (dpyinfo, xev, ¤t_finish, |
| 5757 | current_numcharsp, | 5729 | current_hold_quit); |
| 5758 | ¤t_finish); | 5730 | } |
| 5759 | } | 5731 | } |
| 5760 | else | 5732 | else |
| 5761 | current_finish = x_dispatch_event (xev, xev->xany.display); | 5733 | current_finish = x_dispatch_event (xev, xev->xany.display); |
| @@ -5774,28 +5746,29 @@ event_handler_gdk (gxev, ev, data) | |||
| 5774 | *FINISH is zero if caller should continue reading events. | 5746 | *FINISH is zero if caller should continue reading events. |
| 5775 | *FINISH is X_EVENT_DROP if event should not be passed to the toolkit. | 5747 | *FINISH is X_EVENT_DROP if event should not be passed to the toolkit. |
| 5776 | 5748 | ||
| 5777 | Events representing keys are stored in buffer *BUFP_R, | ||
| 5778 | which can hold up to *NUMCHARSP characters. | ||
| 5779 | We return the number of characters stored into the buffer. */ | 5749 | We return the number of characters stored into the buffer. */ |
| 5780 | 5750 | ||
| 5781 | static int | 5751 | static int |
| 5782 | handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | 5752 | handle_one_xevent (dpyinfo, eventp, finish, hold_quit) |
| 5783 | struct x_display_info *dpyinfo; | 5753 | struct x_display_info *dpyinfo; |
| 5784 | XEvent *eventp; | 5754 | XEvent *eventp; |
| 5785 | /* register */ struct input_event **bufp_r; | ||
| 5786 | /* register */ int *numcharsp; | ||
| 5787 | int *finish; | 5755 | int *finish; |
| 5756 | struct input_event *hold_quit; | ||
| 5788 | { | 5757 | { |
| 5758 | struct input_event inev; | ||
| 5789 | int count = 0; | 5759 | int count = 0; |
| 5760 | int do_help = 0; | ||
| 5790 | int nbytes = 0; | 5761 | int nbytes = 0; |
| 5791 | struct frame *f; | 5762 | struct frame *f; |
| 5792 | struct coding_system coding; | 5763 | struct coding_system coding; |
| 5793 | struct input_event *bufp = *bufp_r; | ||
| 5794 | int numchars = *numcharsp; | ||
| 5795 | XEvent event = *eventp; | 5764 | XEvent event = *eventp; |
| 5796 | 5765 | ||
| 5797 | *finish = X_EVENT_NORMAL; | 5766 | *finish = X_EVENT_NORMAL; |
| 5798 | 5767 | ||
| 5768 | EVENT_INIT (inev); | ||
| 5769 | inev.kind = NO_EVENT; | ||
| 5770 | inev.arg = Qnil; | ||
| 5771 | |||
| 5799 | switch (event.type) | 5772 | switch (event.type) |
| 5800 | { | 5773 | { |
| 5801 | case ClientMessage: | 5774 | case ClientMessage: |
| @@ -5850,8 +5823,10 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 5850 | } | 5823 | } |
| 5851 | /* Not certain about handling scroll bars here */ | 5824 | /* Not certain about handling scroll bars here */ |
| 5852 | #endif /* 0 */ | 5825 | #endif /* 0 */ |
| 5826 | goto done; | ||
| 5853 | } | 5827 | } |
| 5854 | else if (event.xclient.data.l[0] | 5828 | |
| 5829 | if (event.xclient.data.l[0] | ||
| 5855 | == dpyinfo->Xatom_wm_save_yourself) | 5830 | == dpyinfo->Xatom_wm_save_yourself) |
| 5856 | { | 5831 | { |
| 5857 | /* Save state modify the WM_COMMAND property to | 5832 | /* Save state modify the WM_COMMAND property to |
| @@ -5862,11 +5837,9 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 5862 | /* If we have a session manager, don't set this. | 5837 | /* If we have a session manager, don't set this. |
| 5863 | KDE will then start two Emacsen, one for the | 5838 | KDE will then start two Emacsen, one for the |
| 5864 | session manager and one for this. */ | 5839 | session manager and one for this. */ |
| 5865 | if (numchars > 0 | ||
| 5866 | #ifdef HAVE_X_SM | 5840 | #ifdef HAVE_X_SM |
| 5867 | && ! x_session_have_connection () | 5841 | if (! x_session_have_connection ()) |
| 5868 | #endif | 5842 | #endif |
| 5869 | ) | ||
| 5870 | { | 5843 | { |
| 5871 | f = x_top_window_to_frame (dpyinfo, | 5844 | f = x_top_window_to_frame (dpyinfo, |
| 5872 | event.xclient.window); | 5845 | event.xclient.window); |
| @@ -5881,41 +5854,36 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 5881 | event.xclient.window, | 5854 | event.xclient.window, |
| 5882 | 0, 0); | 5855 | 0, 0); |
| 5883 | } | 5856 | } |
| 5857 | goto done; | ||
| 5884 | } | 5858 | } |
| 5885 | else if (event.xclient.data.l[0] | 5859 | |
| 5886 | == dpyinfo->Xatom_wm_delete_window) | 5860 | if (event.xclient.data.l[0] |
| 5861 | == dpyinfo->Xatom_wm_delete_window) | ||
| 5887 | { | 5862 | { |
| 5888 | struct frame *f | 5863 | f = x_any_window_to_frame (dpyinfo, |
| 5889 | = x_any_window_to_frame (dpyinfo, | ||
| 5890 | event.xclient.window); | 5864 | event.xclient.window); |
| 5865 | if (!f) | ||
| 5866 | goto OTHER; /* May be a dialog that is to be removed */ | ||
| 5891 | 5867 | ||
| 5892 | if (f) | 5868 | inev.kind = DELETE_WINDOW_EVENT; |
| 5893 | { | 5869 | XSETFRAME (inev.frame_or_window, f); |
| 5894 | if (numchars == 0) | 5870 | goto done; |
| 5895 | abort (); | ||
| 5896 | |||
| 5897 | bufp->kind = DELETE_WINDOW_EVENT; | ||
| 5898 | XSETFRAME (bufp->frame_or_window, f); | ||
| 5899 | bufp->arg = Qnil; | ||
| 5900 | bufp++; | ||
| 5901 | |||
| 5902 | count += 1; | ||
| 5903 | numchars -= 1; | ||
| 5904 | } | ||
| 5905 | else | ||
| 5906 | goto OTHER; /* May be a dialog that is to be removed */ | ||
| 5907 | } | 5871 | } |
| 5872 | |||
| 5873 | goto done; | ||
| 5908 | } | 5874 | } |
| 5909 | else if (event.xclient.message_type | 5875 | |
| 5876 | if (event.xclient.message_type | ||
| 5910 | == dpyinfo->Xatom_wm_configure_denied) | 5877 | == dpyinfo->Xatom_wm_configure_denied) |
| 5911 | { | 5878 | { |
| 5879 | goto done; | ||
| 5912 | } | 5880 | } |
| 5913 | else if (event.xclient.message_type | 5881 | |
| 5914 | == dpyinfo->Xatom_wm_window_moved) | 5882 | if (event.xclient.message_type |
| 5883 | == dpyinfo->Xatom_wm_window_moved) | ||
| 5915 | { | 5884 | { |
| 5916 | int new_x, new_y; | 5885 | int new_x, new_y; |
| 5917 | struct frame *f | 5886 | f = x_window_to_frame (dpyinfo, event.xclient.window); |
| 5918 | = x_window_to_frame (dpyinfo, event.xclient.window); | ||
| 5919 | 5887 | ||
| 5920 | new_x = event.xclient.data.s[0]; | 5888 | new_x = event.xclient.data.s[0]; |
| 5921 | new_y = event.xclient.data.s[1]; | 5889 | new_y = event.xclient.data.s[1]; |
| @@ -5925,63 +5893,55 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 5925 | f->left_pos = new_x; | 5893 | f->left_pos = new_x; |
| 5926 | f->top_pos = new_y; | 5894 | f->top_pos = new_y; |
| 5927 | } | 5895 | } |
| 5896 | goto done; | ||
| 5928 | } | 5897 | } |
| 5898 | |||
| 5929 | #ifdef HACK_EDITRES | 5899 | #ifdef HACK_EDITRES |
| 5930 | else if (event.xclient.message_type | 5900 | if (event.xclient.message_type |
| 5931 | == dpyinfo->Xatom_editres) | 5901 | == dpyinfo->Xatom_editres) |
| 5932 | { | 5902 | { |
| 5933 | struct frame *f | 5903 | f = x_any_window_to_frame (dpyinfo, event.xclient.window); |
| 5934 | = x_any_window_to_frame (dpyinfo, event.xclient.window); | ||
| 5935 | _XEditResCheckMessages (f->output_data.x->widget, NULL, | 5904 | _XEditResCheckMessages (f->output_data.x->widget, NULL, |
| 5936 | &event, NULL); | 5905 | &event, NULL); |
| 5906 | goto done; | ||
| 5937 | } | 5907 | } |
| 5938 | #endif /* HACK_EDITRES */ | 5908 | #endif /* HACK_EDITRES */ |
| 5939 | else if ((event.xclient.message_type | 5909 | |
| 5940 | == dpyinfo->Xatom_DONE) | 5910 | if ((event.xclient.message_type |
| 5941 | || (event.xclient.message_type | 5911 | == dpyinfo->Xatom_DONE) |
| 5942 | == dpyinfo->Xatom_PAGE)) | 5912 | || (event.xclient.message_type |
| 5913 | == dpyinfo->Xatom_PAGE)) | ||
| 5943 | { | 5914 | { |
| 5944 | /* Ghostview job completed. Kill it. We could | 5915 | /* Ghostview job completed. Kill it. We could |
| 5945 | reply with "Next" if we received "Page", but we | 5916 | reply with "Next" if we received "Page", but we |
| 5946 | currently never do because we are interested in | 5917 | currently never do because we are interested in |
| 5947 | images, only, which should have 1 page. */ | 5918 | images, only, which should have 1 page. */ |
| 5948 | Pixmap pixmap = (Pixmap) event.xclient.data.l[1]; | 5919 | Pixmap pixmap = (Pixmap) event.xclient.data.l[1]; |
| 5949 | struct frame *f | 5920 | f = x_window_to_frame (dpyinfo, event.xclient.window); |
| 5950 | = x_window_to_frame (dpyinfo, event.xclient.window); | ||
| 5951 | x_kill_gs_process (pixmap, f); | 5921 | x_kill_gs_process (pixmap, f); |
| 5952 | expose_frame (f, 0, 0, 0, 0); | 5922 | expose_frame (f, 0, 0, 0, 0); |
| 5923 | goto done; | ||
| 5953 | } | 5924 | } |
| 5925 | |||
| 5954 | #ifdef USE_TOOLKIT_SCROLL_BARS | 5926 | #ifdef USE_TOOLKIT_SCROLL_BARS |
| 5955 | /* Scroll bar callbacks send a ClientMessage from which | 5927 | /* Scroll bar callbacks send a ClientMessage from which |
| 5956 | we construct an input_event. */ | 5928 | we construct an input_event. */ |
| 5957 | else if (event.xclient.message_type | 5929 | if (event.xclient.message_type |
| 5958 | == dpyinfo->Xatom_Scrollbar) | 5930 | == dpyinfo->Xatom_Scrollbar) |
| 5959 | { | 5931 | { |
| 5960 | x_scroll_bar_to_input_event (&event, bufp); | 5932 | x_scroll_bar_to_input_event (&event, &inev); |
| 5961 | ++bufp, ++count, --numchars; | 5933 | *finish = X_EVENT_GOTO_OUT; |
| 5962 | goto out; | 5934 | goto done; |
| 5963 | } | 5935 | } |
| 5964 | #endif /* USE_TOOLKIT_SCROLL_BARS */ | 5936 | #endif /* USE_TOOLKIT_SCROLL_BARS */ |
| 5965 | else | ||
| 5966 | { | ||
| 5967 | struct frame *f | ||
| 5968 | = x_any_window_to_frame (dpyinfo, event.xclient.window); | ||
| 5969 | 5937 | ||
| 5970 | if (f) | 5938 | f = x_any_window_to_frame (dpyinfo, event.xclient.window); |
| 5971 | { | ||
| 5972 | int ret = x_handle_dnd_message (f, &event.xclient, | ||
| 5973 | dpyinfo, bufp); | ||
| 5974 | if (ret > 0) | ||
| 5975 | { | ||
| 5976 | ++bufp, ++count, --numchars; | ||
| 5977 | } | ||
| 5978 | 5939 | ||
| 5979 | if (ret != 0) | 5940 | if (!f) |
| 5980 | *finish = X_EVENT_DROP; | 5941 | goto OTHER; |
| 5981 | } | 5942 | |
| 5982 | else | 5943 | if (x_handle_dnd_message (f, &event.xclient, dpyinfo, &inev)) |
| 5983 | goto OTHER; | 5944 | *finish = X_EVENT_DROP; |
| 5984 | } | ||
| 5985 | } | 5945 | } |
| 5986 | break; | 5946 | break; |
| 5987 | 5947 | ||
| @@ -6001,19 +5961,11 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6001 | { | 5961 | { |
| 6002 | XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event; | 5962 | XSelectionClearEvent *eventp = (XSelectionClearEvent *) &event; |
| 6003 | 5963 | ||
| 6004 | if (numchars == 0) | 5964 | inev.kind = SELECTION_CLEAR_EVENT; |
| 6005 | abort (); | 5965 | SELECTION_EVENT_DISPLAY (&inev) = eventp->display; |
| 6006 | 5966 | SELECTION_EVENT_SELECTION (&inev) = eventp->selection; | |
| 6007 | bufp->kind = SELECTION_CLEAR_EVENT; | 5967 | SELECTION_EVENT_TIME (&inev) = eventp->time; |
| 6008 | SELECTION_EVENT_DISPLAY (bufp) = eventp->display; | 5968 | inev.frame_or_window = Qnil; |
| 6009 | SELECTION_EVENT_SELECTION (bufp) = eventp->selection; | ||
| 6010 | SELECTION_EVENT_TIME (bufp) = eventp->time; | ||
| 6011 | bufp->frame_or_window = Qnil; | ||
| 6012 | bufp->arg = Qnil; | ||
| 6013 | bufp++; | ||
| 6014 | |||
| 6015 | count += 1; | ||
| 6016 | numchars -= 1; | ||
| 6017 | } | 5969 | } |
| 6018 | break; | 5970 | break; |
| 6019 | 5971 | ||
| @@ -6030,22 +5982,14 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6030 | XSelectionRequestEvent *eventp | 5982 | XSelectionRequestEvent *eventp |
| 6031 | = (XSelectionRequestEvent *) &event; | 5983 | = (XSelectionRequestEvent *) &event; |
| 6032 | 5984 | ||
| 6033 | if (numchars == 0) | 5985 | inev.kind = SELECTION_REQUEST_EVENT; |
| 6034 | abort (); | 5986 | SELECTION_EVENT_DISPLAY (&inev) = eventp->display; |
| 6035 | 5987 | SELECTION_EVENT_REQUESTOR (&inev) = eventp->requestor; | |
| 6036 | bufp->kind = SELECTION_REQUEST_EVENT; | 5988 | SELECTION_EVENT_SELECTION (&inev) = eventp->selection; |
| 6037 | SELECTION_EVENT_DISPLAY (bufp) = eventp->display; | 5989 | SELECTION_EVENT_TARGET (&inev) = eventp->target; |
| 6038 | SELECTION_EVENT_REQUESTOR (bufp) = eventp->requestor; | 5990 | SELECTION_EVENT_PROPERTY (&inev) = eventp->property; |
| 6039 | SELECTION_EVENT_SELECTION (bufp) = eventp->selection; | 5991 | SELECTION_EVENT_TIME (&inev) = eventp->time; |
| 6040 | SELECTION_EVENT_TARGET (bufp) = eventp->target; | 5992 | inev.frame_or_window = Qnil; |
| 6041 | SELECTION_EVENT_PROPERTY (bufp) = eventp->property; | ||
| 6042 | SELECTION_EVENT_TIME (bufp) = eventp->time; | ||
| 6043 | bufp->frame_or_window = Qnil; | ||
| 6044 | bufp->arg = Qnil; | ||
| 6045 | bufp++; | ||
| 6046 | |||
| 6047 | count += 1; | ||
| 6048 | numchars -= 1; | ||
| 6049 | } | 5993 | } |
| 6050 | break; | 5994 | break; |
| 6051 | 5995 | ||
| @@ -6075,7 +6019,6 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6075 | FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN; | 6019 | FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_UNKNOWN; |
| 6076 | } | 6020 | } |
| 6077 | goto OTHER; | 6021 | goto OTHER; |
| 6078 | break; | ||
| 6079 | 6022 | ||
| 6080 | case Expose: | 6023 | case Expose: |
| 6081 | f = x_window_to_frame (dpyinfo, event.xexpose.window); | 6024 | f = x_window_to_frame (dpyinfo, event.xexpose.window); |
| @@ -6177,12 +6120,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6177 | { | 6120 | { |
| 6178 | f->async_iconified = 1; | 6121 | f->async_iconified = 1; |
| 6179 | 6122 | ||
| 6180 | bufp->kind = ICONIFY_EVENT; | 6123 | inev.kind = ICONIFY_EVENT; |
| 6181 | XSETFRAME (bufp->frame_or_window, f); | 6124 | XSETFRAME (inev.frame_or_window, f); |
| 6182 | bufp->arg = Qnil; | ||
| 6183 | bufp++; | ||
| 6184 | count++; | ||
| 6185 | numchars--; | ||
| 6186 | } | 6125 | } |
| 6187 | } | 6126 | } |
| 6188 | goto OTHER; | 6127 | goto OTHER; |
| @@ -6214,12 +6153,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6214 | 6153 | ||
| 6215 | if (f->iconified) | 6154 | if (f->iconified) |
| 6216 | { | 6155 | { |
| 6217 | bufp->kind = DEICONIFY_EVENT; | 6156 | inev.kind = DEICONIFY_EVENT; |
| 6218 | XSETFRAME (bufp->frame_or_window, f); | 6157 | XSETFRAME (inev.frame_or_window, f); |
| 6219 | bufp->arg = Qnil; | ||
| 6220 | bufp++; | ||
| 6221 | count++; | ||
| 6222 | numchars--; | ||
| 6223 | } | 6158 | } |
| 6224 | else if (! NILP (Vframe_list) | 6159 | else if (! NILP (Vframe_list) |
| 6225 | && ! NILP (XCDR (Vframe_list))) | 6160 | && ! NILP (XCDR (Vframe_list))) |
| @@ -6280,6 +6215,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6280 | int copy_bufsiz = sizeof (copy_buffer); | 6215 | int copy_bufsiz = sizeof (copy_buffer); |
| 6281 | int modifiers; | 6216 | int modifiers; |
| 6282 | Lisp_Object coding_system = Qlatin_1; | 6217 | Lisp_Object coding_system = Qlatin_1; |
| 6218 | Lisp_Object c; | ||
| 6283 | 6219 | ||
| 6284 | event.xkey.state | 6220 | event.xkey.state |
| 6285 | |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f), | 6221 | |= x_emacs_to_x_modifiers (FRAME_X_DISPLAY_INFO (f), |
| @@ -6373,49 +6309,37 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6373 | 6309 | ||
| 6374 | orig_keysym = keysym; | 6310 | orig_keysym = keysym; |
| 6375 | 6311 | ||
| 6376 | if (numchars > 1) | 6312 | /* Common for all keysym input events. */ |
| 6377 | { | 6313 | XSETFRAME (inev.frame_or_window, f); |
| 6378 | Lisp_Object c; | 6314 | inev.modifiers |
| 6315 | = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), modifiers); | ||
| 6316 | inev.timestamp = event.xkey.time; | ||
| 6379 | 6317 | ||
| 6380 | /* First deal with keysyms which have defined | 6318 | /* First deal with keysyms which have defined |
| 6381 | translations to characters. */ | 6319 | translations to characters. */ |
| 6382 | if (keysym >= 32 && keysym < 128) | 6320 | if (keysym >= 32 && keysym < 128) |
| 6383 | /* Avoid explicitly decoding each ASCII character. */ | 6321 | /* Avoid explicitly decoding each ASCII character. */ |
| 6384 | { | 6322 | { |
| 6385 | bufp->kind = ASCII_KEYSTROKE_EVENT; | 6323 | inev.kind = ASCII_KEYSTROKE_EVENT; |
| 6386 | bufp->code = keysym; | 6324 | inev.code = keysym; |
| 6387 | XSETFRAME (bufp->frame_or_window, f); | 6325 | goto done_keysym; |
| 6388 | bufp->arg = Qnil; | 6326 | } |
| 6389 | bufp->modifiers | 6327 | |
| 6390 | = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), | 6328 | /* Now non-ASCII. */ |
| 6391 | modifiers); | 6329 | if (HASH_TABLE_P (Vx_keysym_table) |
| 6392 | bufp->timestamp = event.xkey.time; | 6330 | && (NATNUMP (c = Fgethash (make_number (keysym), |
| 6393 | bufp++; | 6331 | Vx_keysym_table, |
| 6394 | count++; | 6332 | Qnil)))) |
| 6395 | numchars--; | 6333 | { |
| 6396 | } | 6334 | inev.kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c)) |
| 6397 | /* Now non-ASCII. */ | 6335 | ? ASCII_KEYSTROKE_EVENT |
| 6398 | else if (HASH_TABLE_P (Vx_keysym_table) | 6336 | : MULTIBYTE_CHAR_KEYSTROKE_EVENT); |
| 6399 | && (NATNUMP (c = Fgethash (make_number (keysym), | 6337 | inev.code = XFASTINT (c); |
| 6400 | Vx_keysym_table, | 6338 | goto done_keysym; |
| 6401 | Qnil)))) | 6339 | } |
| 6402 | { | 6340 | |
| 6403 | bufp->kind = (SINGLE_BYTE_CHAR_P (XFASTINT (c)) | 6341 | /* Random non-modifier sorts of keysyms. */ |
| 6404 | ? ASCII_KEYSTROKE_EVENT | 6342 | if (((keysym >= XK_BackSpace && keysym <= XK_Escape) |
| 6405 | : MULTIBYTE_CHAR_KEYSTROKE_EVENT); | ||
| 6406 | bufp->code = XFASTINT (c); | ||
| 6407 | XSETFRAME (bufp->frame_or_window, f); | ||
| 6408 | bufp->arg = Qnil; | ||
| 6409 | bufp->modifiers | ||
| 6410 | = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), | ||
| 6411 | modifiers); | ||
| 6412 | bufp->timestamp = event.xkey.time; | ||
| 6413 | bufp++; | ||
| 6414 | count++; | ||
| 6415 | numchars--; | ||
| 6416 | } | ||
| 6417 | /* Random non-modifier sorts of keysyms. */ | ||
| 6418 | else if (((keysym >= XK_BackSpace && keysym <= XK_Escape) | ||
| 6419 | || keysym == XK_Delete | 6343 | || keysym == XK_Delete |
| 6420 | #ifdef XK_ISO_Left_Tab | 6344 | #ifdef XK_ISO_Left_Tab |
| 6421 | || (keysym >= XK_ISO_Left_Tab | 6345 | || (keysym >= XK_ISO_Left_Tab |
| @@ -6496,104 +6420,80 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6496 | <= XK_ISO_Last_Group_Lock) | 6420 | <= XK_ISO_Last_Group_Lock) |
| 6497 | #endif | 6421 | #endif |
| 6498 | )) | 6422 | )) |
| 6499 | { | 6423 | { |
| 6500 | if (temp_index == sizeof temp_buffer / sizeof (short)) | 6424 | STORE_KEYSYM_FOR_DEBUG (keysym); |
| 6501 | temp_index = 0; | 6425 | /* make_lispy_event will convert this to a symbolic |
| 6502 | temp_buffer[temp_index++] = keysym; | 6426 | key. */ |
| 6503 | /* make_lispy_event will convert this to a symbolic | 6427 | inev.kind = NON_ASCII_KEYSTROKE_EVENT; |
| 6504 | key. */ | 6428 | inev.code = keysym; |
| 6505 | bufp->kind = NON_ASCII_KEYSTROKE_EVENT; | 6429 | goto done_keysym; |
| 6506 | bufp->code = keysym; | 6430 | } |
| 6507 | XSETFRAME (bufp->frame_or_window, f); | ||
| 6508 | bufp->arg = Qnil; | ||
| 6509 | bufp->modifiers | ||
| 6510 | = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), | ||
| 6511 | modifiers); | ||
| 6512 | bufp->timestamp = event.xkey.time; | ||
| 6513 | bufp++; | ||
| 6514 | count++; | ||
| 6515 | numchars--; | ||
| 6516 | } | ||
| 6517 | else if (numchars > nbytes) | ||
| 6518 | { /* Raw bytes, not keysym. */ | ||
| 6519 | register int i; | ||
| 6520 | register int c; | ||
| 6521 | int nchars, len; | ||
| 6522 | |||
| 6523 | /* The input should be decoded with `coding_system' | ||
| 6524 | which depends on which X*LookupString function | ||
| 6525 | we used just above and the locale. */ | ||
| 6526 | setup_coding_system (coding_system, &coding); | ||
| 6527 | coding.src_multibyte = 0; | ||
| 6528 | coding.dst_multibyte = 1; | ||
| 6529 | /* The input is converted to events, thus we can't | ||
| 6530 | handle composition. Anyway, there's no XIM that | ||
| 6531 | gives us composition information. */ | ||
| 6532 | coding.composing = COMPOSITION_DISABLED; | ||
| 6533 | |||
| 6534 | for (i = 0; i < nbytes; i++) | ||
| 6535 | { | ||
| 6536 | if (temp_index == (sizeof temp_buffer | ||
| 6537 | / sizeof (short))) | ||
| 6538 | temp_index = 0; | ||
| 6539 | temp_buffer[temp_index++] = copy_bufptr[i]; | ||
| 6540 | } | ||
| 6541 | 6431 | ||
| 6542 | { | 6432 | { /* Raw bytes, not keysym. */ |
| 6543 | /* Decode the input data. */ | 6433 | register int i; |
| 6544 | int require; | 6434 | register int c; |
| 6545 | unsigned char *p; | 6435 | int nchars, len; |
| 6546 | 6436 | ||
| 6547 | require = decoding_buffer_size (&coding, nbytes); | 6437 | /* The input should be decoded with `coding_system' |
| 6548 | p = (unsigned char *) alloca (require); | 6438 | which depends on which X*LookupString function |
| 6549 | coding.mode |= CODING_MODE_LAST_BLOCK; | 6439 | we used just above and the locale. */ |
| 6550 | /* We explicitly disable composition | 6440 | setup_coding_system (coding_system, &coding); |
| 6551 | handling because key data should | 6441 | coding.src_multibyte = 0; |
| 6552 | not contain any composition | 6442 | coding.dst_multibyte = 1; |
| 6553 | sequence. */ | 6443 | /* The input is converted to events, thus we can't |
| 6554 | coding.composing = COMPOSITION_DISABLED; | 6444 | handle composition. Anyway, there's no XIM that |
| 6555 | decode_coding (&coding, copy_bufptr, p, | 6445 | gives us composition information. */ |
| 6556 | nbytes, require); | 6446 | coding.composing = COMPOSITION_DISABLED; |
| 6557 | nbytes = coding.produced; | 6447 | |
| 6558 | nchars = coding.produced_char; | 6448 | for (i = 0; i < nbytes; i++) |
| 6559 | copy_bufptr = p; | 6449 | { |
| 6560 | } | 6450 | STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]); |
| 6451 | } | ||
| 6561 | 6452 | ||
| 6562 | /* Convert the input data to a sequence of | 6453 | { |
| 6563 | character events. */ | 6454 | /* Decode the input data. */ |
| 6564 | for (i = 0; i < nbytes; i += len) | 6455 | int require; |
| 6565 | { | 6456 | unsigned char *p; |
| 6566 | if (nchars == nbytes) | 6457 | |
| 6567 | c = copy_bufptr[i], len = 1; | 6458 | require = decoding_buffer_size (&coding, nbytes); |
| 6568 | else | 6459 | p = (unsigned char *) alloca (require); |
| 6569 | c = STRING_CHAR_AND_LENGTH (copy_bufptr + i, | 6460 | coding.mode |= CODING_MODE_LAST_BLOCK; |
| 6570 | nbytes - i, len); | 6461 | /* We explicitly disable composition handling because |
| 6571 | 6462 | key data should not contain any composition sequence. */ | |
| 6572 | bufp->kind = (SINGLE_BYTE_CHAR_P (c) | 6463 | coding.composing = COMPOSITION_DISABLED; |
| 6573 | ? ASCII_KEYSTROKE_EVENT | 6464 | decode_coding (&coding, copy_bufptr, p, nbytes, require); |
| 6574 | : MULTIBYTE_CHAR_KEYSTROKE_EVENT); | 6465 | nbytes = coding.produced; |
| 6575 | bufp->code = c; | 6466 | nchars = coding.produced_char; |
| 6576 | XSETFRAME (bufp->frame_or_window, f); | 6467 | copy_bufptr = p; |
| 6577 | bufp->arg = Qnil; | 6468 | } |
| 6578 | bufp->modifiers | ||
| 6579 | = x_x_to_emacs_modifiers (FRAME_X_DISPLAY_INFO (f), | ||
| 6580 | modifiers); | ||
| 6581 | bufp->timestamp = event.xkey.time; | ||
| 6582 | bufp++; | ||
| 6583 | } | ||
| 6584 | 6469 | ||
| 6585 | count += nchars; | 6470 | /* Convert the input data to a sequence of |
| 6586 | numchars -= nchars; | 6471 | character events. */ |
| 6472 | for (i = 0; i < nbytes; i += len) | ||
| 6473 | { | ||
| 6474 | if (nchars == nbytes) | ||
| 6475 | c = copy_bufptr[i], len = 1; | ||
| 6476 | else | ||
| 6477 | c = STRING_CHAR_AND_LENGTH (copy_bufptr + i, | ||
| 6478 | nbytes - i, len); | ||
| 6479 | inev.kind = (SINGLE_BYTE_CHAR_P (c) | ||
| 6480 | ? ASCII_KEYSTROKE_EVENT | ||
| 6481 | : MULTIBYTE_CHAR_KEYSTROKE_EVENT); | ||
| 6482 | inev.code = c; | ||
| 6483 | kbd_buffer_store_event_hold (&inev, hold_quit); | ||
| 6484 | } | ||
| 6587 | 6485 | ||
| 6588 | if (keysym == NoSymbol) | 6486 | /* Previous code updated count by nchars rather than nbytes, |
| 6589 | break; | 6487 | but that seems bogus to me. ++kfs */ |
| 6590 | } | 6488 | count += nbytes; |
| 6591 | else | 6489 | |
| 6592 | abort (); | 6490 | inev.kind = NO_EVENT; /* Already stored above. */ |
| 6593 | } | 6491 | |
| 6594 | else | 6492 | if (keysym == NoSymbol) |
| 6595 | abort (); | 6493 | break; |
| 6494 | } | ||
| 6596 | } | 6495 | } |
| 6496 | done_keysym: | ||
| 6597 | #ifdef HAVE_X_I18N | 6497 | #ifdef HAVE_X_I18N |
| 6598 | /* Don't dispatch this event since XtDispatchEvent calls | 6498 | /* Don't dispatch this event since XtDispatchEvent calls |
| 6599 | XFilterEvent, and two calls in a row may freeze the | 6499 | XFilterEvent, and two calls in a row may freeze the |
| @@ -6614,63 +6514,38 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6614 | #endif | 6514 | #endif |
| 6615 | 6515 | ||
| 6616 | case EnterNotify: | 6516 | case EnterNotify: |
| 6617 | { | 6517 | x_detect_focus_change (dpyinfo, &event, &inev); |
| 6618 | int n; | ||
| 6619 | |||
| 6620 | n = x_detect_focus_change (dpyinfo, &event, bufp, numchars); | ||
| 6621 | if (n > 0) | ||
| 6622 | { | ||
| 6623 | bufp += n, count += n, numchars -= n; | ||
| 6624 | } | ||
| 6625 | 6518 | ||
| 6626 | f = x_any_window_to_frame (dpyinfo, event.xcrossing.window); | 6519 | f = x_any_window_to_frame (dpyinfo, event.xcrossing.window); |
| 6627 | 6520 | ||
| 6628 | #if 0 | 6521 | #if 0 |
| 6629 | if (event.xcrossing.focus) | 6522 | if (event.xcrossing.focus) |
| 6630 | { | 6523 | { |
| 6631 | /* Avoid nasty pop/raise loops. */ | 6524 | /* Avoid nasty pop/raise loops. */ |
| 6632 | if (f && (!(f->auto_raise) | 6525 | if (f && (!(f->auto_raise) |
| 6633 | || !(f->auto_lower) | 6526 | || !(f->auto_lower) |
| 6634 | || (event.xcrossing.time - enter_timestamp) > 500)) | 6527 | || (event.xcrossing.time - enter_timestamp) > 500)) |
| 6635 | { | 6528 | { |
| 6636 | x_new_focus_frame (dpyinfo, f); | 6529 | x_new_focus_frame (dpyinfo, f); |
| 6637 | enter_timestamp = event.xcrossing.time; | 6530 | enter_timestamp = event.xcrossing.time; |
| 6638 | } | 6531 | } |
| 6639 | } | 6532 | } |
| 6640 | else if (f == dpyinfo->x_focus_frame) | 6533 | else if (f == dpyinfo->x_focus_frame) |
| 6641 | x_new_focus_frame (dpyinfo, 0); | 6534 | x_new_focus_frame (dpyinfo, 0); |
| 6642 | #endif | 6535 | #endif |
| 6643 | 6536 | ||
| 6644 | /* EnterNotify counts as mouse movement, | 6537 | /* EnterNotify counts as mouse movement, |
| 6645 | so update things that depend on mouse position. */ | 6538 | so update things that depend on mouse position. */ |
| 6646 | if (f && !f->output_data.x->hourglass_p) | 6539 | if (f && !f->output_data.x->hourglass_p) |
| 6647 | note_mouse_movement (f, &event.xmotion); | 6540 | note_mouse_movement (f, &event.xmotion); |
| 6648 | goto OTHER; | 6541 | goto OTHER; |
| 6649 | } | ||
| 6650 | 6542 | ||
| 6651 | case FocusIn: | 6543 | case FocusIn: |
| 6652 | { | 6544 | x_detect_focus_change (dpyinfo, &event, &inev); |
| 6653 | int n; | ||
| 6654 | |||
| 6655 | n = x_detect_focus_change (dpyinfo, &event, bufp, numchars); | ||
| 6656 | if (n > 0) | ||
| 6657 | { | ||
| 6658 | bufp += n, count += n, numchars -= n; | ||
| 6659 | } | ||
| 6660 | } | ||
| 6661 | |||
| 6662 | goto OTHER; | 6545 | goto OTHER; |
| 6663 | 6546 | ||
| 6664 | case LeaveNotify: | 6547 | case LeaveNotify: |
| 6665 | { | 6548 | x_detect_focus_change (dpyinfo, &event, &inev); |
| 6666 | int n; | ||
| 6667 | |||
| 6668 | n = x_detect_focus_change (dpyinfo, &event, bufp, numchars); | ||
| 6669 | if (n > 0) | ||
| 6670 | { | ||
| 6671 | bufp += n, count += n, numchars -= n; | ||
| 6672 | } | ||
| 6673 | } | ||
| 6674 | 6549 | ||
| 6675 | f = x_top_window_to_frame (dpyinfo, event.xcrossing.window); | 6550 | f = x_top_window_to_frame (dpyinfo, event.xcrossing.window); |
| 6676 | if (f) | 6551 | if (f) |
| @@ -6688,31 +6563,12 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6688 | Otherwise, the startup message is cleared when | 6563 | Otherwise, the startup message is cleared when |
| 6689 | the mouse leaves the frame. */ | 6564 | the mouse leaves the frame. */ |
| 6690 | if (any_help_event_p) | 6565 | if (any_help_event_p) |
| 6691 | { | 6566 | do_help = -1; |
| 6692 | Lisp_Object frame; | ||
| 6693 | int n; | ||
| 6694 | |||
| 6695 | XSETFRAME (frame, f); | ||
| 6696 | help_echo_string = Qnil; | ||
| 6697 | n = gen_help_event (bufp, numchars, | ||
| 6698 | Qnil, frame, Qnil, Qnil, 0); | ||
| 6699 | bufp += n, count += n, numchars -= n; | ||
| 6700 | } | ||
| 6701 | |||
| 6702 | } | 6567 | } |
| 6703 | goto OTHER; | 6568 | goto OTHER; |
| 6704 | 6569 | ||
| 6705 | case FocusOut: | 6570 | case FocusOut: |
| 6706 | { | 6571 | x_detect_focus_change (dpyinfo, &event, &inev); |
| 6707 | int n; | ||
| 6708 | |||
| 6709 | n = x_detect_focus_change (dpyinfo, &event, bufp, numchars); | ||
| 6710 | if (n > 0) | ||
| 6711 | { | ||
| 6712 | bufp += n, count += n, numchars -= n; | ||
| 6713 | } | ||
| 6714 | } | ||
| 6715 | |||
| 6716 | goto OTHER; | 6572 | goto OTHER; |
| 6717 | 6573 | ||
| 6718 | case MotionNotify: | 6574 | case MotionNotify: |
| @@ -6750,13 +6606,10 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6750 | will be selected iff it is active. */ | 6606 | will be selected iff it is active. */ |
| 6751 | if (WINDOWP (window) | 6607 | if (WINDOWP (window) |
| 6752 | && !EQ (window, last_window) | 6608 | && !EQ (window, last_window) |
| 6753 | && !EQ (window, selected_window) | 6609 | && !EQ (window, selected_window)) |
| 6754 | && numchars > 0) | ||
| 6755 | { | 6610 | { |
| 6756 | bufp->kind = SELECT_WINDOW_EVENT; | 6611 | inev.kind = SELECT_WINDOW_EVENT; |
| 6757 | bufp->frame_or_window = window; | 6612 | inev.frame_or_window = window; |
| 6758 | bufp->arg = Qnil; | ||
| 6759 | ++bufp, ++count, --numchars; | ||
| 6760 | } | 6613 | } |
| 6761 | 6614 | ||
| 6762 | last_window=window; | 6615 | last_window=window; |
| @@ -6783,22 +6636,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6783 | has changed, generate a HELP_EVENT. */ | 6636 | has changed, generate a HELP_EVENT. */ |
| 6784 | if (!NILP (help_echo_string) | 6637 | if (!NILP (help_echo_string) |
| 6785 | || !NILP (previous_help_echo_string)) | 6638 | || !NILP (previous_help_echo_string)) |
| 6786 | { | 6639 | do_help = 1; |
| 6787 | Lisp_Object frame; | ||
| 6788 | int n; | ||
| 6789 | |||
| 6790 | if (f) | ||
| 6791 | XSETFRAME (frame, f); | ||
| 6792 | else | ||
| 6793 | frame = Qnil; | ||
| 6794 | |||
| 6795 | any_help_event_p = 1; | ||
| 6796 | n = gen_help_event (bufp, numchars, help_echo_string, frame, | ||
| 6797 | help_echo_window, help_echo_object, | ||
| 6798 | help_echo_pos); | ||
| 6799 | bufp += n, count += n, numchars -= n; | ||
| 6800 | } | ||
| 6801 | |||
| 6802 | goto OTHER; | 6640 | goto OTHER; |
| 6803 | } | 6641 | } |
| 6804 | 6642 | ||
| @@ -6882,10 +6720,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6882 | { | 6720 | { |
| 6883 | /* If we decide we want to generate an event to be seen | 6721 | /* If we decide we want to generate an event to be seen |
| 6884 | by the rest of Emacs, we put it here. */ | 6722 | by the rest of Emacs, we put it here. */ |
| 6885 | struct input_event emacs_event; | ||
| 6886 | int tool_bar_p = 0; | 6723 | int tool_bar_p = 0; |
| 6887 | 6724 | ||
| 6888 | emacs_event.kind = NO_EVENT; | ||
| 6889 | bzero (&compose_status, sizeof (compose_status)); | 6725 | bzero (&compose_status, sizeof (compose_status)); |
| 6890 | 6726 | ||
| 6891 | if (dpyinfo->grabbed | 6727 | if (dpyinfo->grabbed |
| @@ -6925,7 +6761,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6925 | #if defined (USE_X_TOOLKIT) || defined (USE_GTK) | 6761 | #if defined (USE_X_TOOLKIT) || defined (USE_GTK) |
| 6926 | if (! popup_activated ()) | 6762 | if (! popup_activated ()) |
| 6927 | #endif | 6763 | #endif |
| 6928 | construct_mouse_click (&emacs_event, &event, f); | 6764 | construct_mouse_click (&inev, &event, f); |
| 6929 | } | 6765 | } |
| 6930 | } | 6766 | } |
| 6931 | else | 6767 | else |
| @@ -6939,12 +6775,12 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6939 | scroll bars. */ | 6775 | scroll bars. */ |
| 6940 | if (bar && event.xbutton.state & ControlMask) | 6776 | if (bar && event.xbutton.state & ControlMask) |
| 6941 | { | 6777 | { |
| 6942 | x_scroll_bar_handle_click (bar, &event, &emacs_event); | 6778 | x_scroll_bar_handle_click (bar, &event, &inev); |
| 6943 | *finish = X_EVENT_DROP; | 6779 | *finish = X_EVENT_DROP; |
| 6944 | } | 6780 | } |
| 6945 | #else /* not USE_TOOLKIT_SCROLL_BARS */ | 6781 | #else /* not USE_TOOLKIT_SCROLL_BARS */ |
| 6946 | if (bar) | 6782 | if (bar) |
| 6947 | x_scroll_bar_handle_click (bar, &event, &emacs_event); | 6783 | x_scroll_bar_handle_click (bar, &event, &inev); |
| 6948 | #endif /* not USE_TOOLKIT_SCROLL_BARS */ | 6784 | #endif /* not USE_TOOLKIT_SCROLL_BARS */ |
| 6949 | } | 6785 | } |
| 6950 | 6786 | ||
| @@ -6965,14 +6801,6 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 6965 | else | 6801 | else |
| 6966 | dpyinfo->grabbed &= ~(1 << event.xbutton.button); | 6802 | dpyinfo->grabbed &= ~(1 << event.xbutton.button); |
| 6967 | 6803 | ||
| 6968 | if (numchars >= 1 && emacs_event.kind != NO_EVENT) | ||
| 6969 | { | ||
| 6970 | bcopy (&emacs_event, bufp, sizeof (struct input_event)); | ||
| 6971 | bufp++; | ||
| 6972 | count++; | ||
| 6973 | numchars--; | ||
| 6974 | } | ||
| 6975 | |||
| 6976 | #if defined (USE_X_TOOLKIT) || defined (USE_GTK) | 6804 | #if defined (USE_X_TOOLKIT) || defined (USE_GTK) |
| 6977 | f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window); | 6805 | f = x_menubar_window_to_frame (dpyinfo, event.xbutton.window); |
| 6978 | /* For a down-event in the menu bar, | 6806 | /* For a down-event in the menu bar, |
| @@ -7059,16 +6887,38 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish) | |||
| 7059 | break; | 6887 | break; |
| 7060 | } | 6888 | } |
| 7061 | 6889 | ||
| 7062 | goto ret; | 6890 | done: |
| 6891 | if (inev.kind != NO_EVENT) | ||
| 6892 | { | ||
| 6893 | kbd_buffer_store_event_hold (&inev, hold_quit); | ||
| 6894 | count++; | ||
| 6895 | } | ||
| 7063 | 6896 | ||
| 7064 | out: | 6897 | if (do_help |
| 7065 | *finish = X_EVENT_GOTO_OUT; | 6898 | && !(hold_quit && hold_quit->kind != NO_EVENT)) |
| 6899 | { | ||
| 6900 | Lisp_Object frame; | ||
| 7066 | 6901 | ||
| 7067 | ret: | 6902 | if (f) |
| 7068 | *bufp_r = bufp; | 6903 | XSETFRAME (frame, f); |
| 7069 | *numcharsp = numchars; | 6904 | else |
| 7070 | *eventp = event; | 6905 | frame = Qnil; |
| 7071 | 6906 | ||
| 6907 | if (do_help > 0) | ||
| 6908 | { | ||
| 6909 | any_help_event_p = 1; | ||
| 6910 | gen_help_event (help_echo_string, frame, help_echo_window, | ||
| 6911 | help_echo_object, help_echo_pos); | ||
| 6912 | } | ||
| 6913 | else | ||
| 6914 | { | ||
| 6915 | help_echo_string = Qnil; | ||
| 6916 | gen_help_event (Qnil, frame, Qnil, Qnil, 0); | ||
| 6917 | } | ||
| 6918 | count++; | ||
| 6919 | } | ||
| 6920 | |||
| 6921 | *eventp = event; | ||
| 7072 | return count; | 6922 | return count; |
| 7073 | } | 6923 | } |
| 7074 | 6924 | ||
| @@ -7084,28 +6934,12 @@ x_dispatch_event (event, display) | |||
| 7084 | Display *display; | 6934 | Display *display; |
| 7085 | { | 6935 | { |
| 7086 | struct x_display_info *dpyinfo; | 6936 | struct x_display_info *dpyinfo; |
| 7087 | struct input_event bufp[10]; | ||
| 7088 | struct input_event *bufpp; | ||
| 7089 | int numchars = 10; | ||
| 7090 | int finish = X_EVENT_NORMAL; | 6937 | int finish = X_EVENT_NORMAL; |
| 7091 | 6938 | ||
| 7092 | for (bufpp = bufp; bufpp != bufp + 10; bufpp++) | ||
| 7093 | EVENT_INIT (*bufpp); | ||
| 7094 | bufpp = bufp; | ||
| 7095 | |||
| 7096 | dpyinfo = x_display_info_for_display (display); | 6939 | dpyinfo = x_display_info_for_display (display); |
| 7097 | 6940 | ||
| 7098 | if (dpyinfo) | 6941 | if (dpyinfo) |
| 7099 | { | 6942 | handle_one_xevent (dpyinfo, event, &finish, 0); |
| 7100 | int i, events; | ||
| 7101 | events = handle_one_xevent (dpyinfo, | ||
| 7102 | event, | ||
| 7103 | &bufpp, | ||
| 7104 | &numchars, | ||
| 7105 | &finish); | ||
| 7106 | for (i = 0; i < events; ++i) | ||
| 7107 | kbd_buffer_store_event (&bufp[i]); | ||
| 7108 | } | ||
| 7109 | 6943 | ||
| 7110 | return finish; | 6944 | return finish; |
| 7111 | } | 6945 | } |
| @@ -7115,19 +6949,16 @@ x_dispatch_event (event, display) | |||
| 7115 | This routine is called by the SIGIO handler. | 6949 | This routine is called by the SIGIO handler. |
| 7116 | We return as soon as there are no more events to be read. | 6950 | We return as soon as there are no more events to be read. |
| 7117 | 6951 | ||
| 7118 | Events representing keys are stored in buffer BUFP, | ||
| 7119 | which can hold up to NUMCHARS characters. | ||
| 7120 | We return the number of characters stored into the buffer, | 6952 | We return the number of characters stored into the buffer, |
| 7121 | thus pretending to be `read'. | 6953 | thus pretending to be `read'. |
| 7122 | 6954 | ||
| 7123 | EXPECTED is nonzero if the caller knows input is available. */ | 6955 | EXPECTED is nonzero if the caller knows input is available. */ |
| 7124 | 6956 | ||
| 7125 | static int | 6957 | static int |
| 7126 | XTread_socket (sd, bufp, numchars, expected) | 6958 | XTread_socket (sd, expected, hold_quit) |
| 7127 | register int sd; | 6959 | register int sd; |
| 7128 | /* register */ struct input_event *bufp; | ||
| 7129 | /* register */ int numchars; | ||
| 7130 | int expected; | 6960 | int expected; |
| 6961 | struct input_event *hold_quit; | ||
| 7131 | { | 6962 | { |
| 7132 | int count = 0; | 6963 | int count = 0; |
| 7133 | XEvent event; | 6964 | XEvent event; |
| @@ -7146,9 +6977,6 @@ XTread_socket (sd, bufp, numchars, expected) | |||
| 7146 | /* So people can tell when we have read the available input. */ | 6977 | /* So people can tell when we have read the available input. */ |
| 7147 | input_signal_count++; | 6978 | input_signal_count++; |
| 7148 | 6979 | ||
| 7149 | if (numchars <= 0) | ||
| 7150 | abort (); /* Don't think this happens. */ | ||
| 7151 | |||
| 7152 | ++handling_signal; | 6980 | ++handling_signal; |
| 7153 | 6981 | ||
| 7154 | /* Find the display we are supposed to read input for. | 6982 | /* Find the display we are supposed to read input for. |
| @@ -7190,9 +7018,18 @@ XTread_socket (sd, bufp, numchars, expected) | |||
| 7190 | } | 7018 | } |
| 7191 | 7019 | ||
| 7192 | #ifdef HAVE_X_SM | 7020 | #ifdef HAVE_X_SM |
| 7193 | BLOCK_INPUT; | 7021 | { |
| 7194 | count += x_session_check_input (bufp, &numchars); | 7022 | struct input_event inev; |
| 7195 | UNBLOCK_INPUT; | 7023 | BLOCK_INPUT; |
| 7024 | /* We don't need to EVENT_INIT (inev) here, as | ||
| 7025 | x_session_check_input copies an entire input_event. */ | ||
| 7026 | if (x_session_check_input (&inev)) | ||
| 7027 | { | ||
| 7028 | kbd_buffer_store_event_hold (&inev, hold_quit); | ||
| 7029 | count++; | ||
| 7030 | } | ||
| 7031 | UNBLOCK_INPUT; | ||
| 7032 | } | ||
| 7196 | #endif | 7033 | #endif |
| 7197 | 7034 | ||
| 7198 | #ifndef USE_GTK | 7035 | #ifndef USE_GTK |
| @@ -7209,11 +7046,7 @@ XTread_socket (sd, bufp, numchars, expected) | |||
| 7209 | #endif | 7046 | #endif |
| 7210 | event_found = 1; | 7047 | event_found = 1; |
| 7211 | 7048 | ||
| 7212 | count += handle_one_xevent (dpyinfo, | 7049 | count += handle_one_xevent (dpyinfo, &event, &finish, hold_quit); |
| 7213 | &event, | ||
| 7214 | &bufp, | ||
| 7215 | &numchars, | ||
| 7216 | &finish); | ||
| 7217 | 7050 | ||
| 7218 | if (finish == X_EVENT_GOTO_OUT) | 7051 | if (finish == X_EVENT_GOTO_OUT) |
| 7219 | goto out; | 7052 | goto out; |
| @@ -7234,14 +7067,13 @@ XTread_socket (sd, bufp, numchars, expected) | |||
| 7234 | while (gtk_events_pending ()) | 7067 | while (gtk_events_pending ()) |
| 7235 | { | 7068 | { |
| 7236 | current_count = count; | 7069 | current_count = count; |
| 7237 | current_numcharsp = &numchars; | 7070 | current_hold_quit = hold_quit; |
| 7238 | current_bufp = &bufp; | ||
| 7239 | 7071 | ||
| 7240 | gtk_main_iteration (); | 7072 | gtk_main_iteration (); |
| 7241 | 7073 | ||
| 7242 | count = current_count; | 7074 | count = current_count; |
| 7243 | current_bufp = 0; | 7075 | current_count = -1; |
| 7244 | current_numcharsp = 0; | 7076 | current_hold_quit = 0; |
| 7245 | 7077 | ||
| 7246 | if (current_finish == X_EVENT_GOTO_OUT) | 7078 | if (current_finish == X_EVENT_GOTO_OUT) |
| 7247 | break; | 7079 | break; |
| @@ -7281,8 +7113,9 @@ XTread_socket (sd, bufp, numchars, expected) | |||
| 7281 | pending_autoraise_frame = 0; | 7113 | pending_autoraise_frame = 0; |
| 7282 | } | 7114 | } |
| 7283 | 7115 | ||
| 7284 | UNBLOCK_INPUT; | ||
| 7285 | --handling_signal; | 7116 | --handling_signal; |
| 7117 | UNBLOCK_INPUT; | ||
| 7118 | |||
| 7286 | return count; | 7119 | return count; |
| 7287 | } | 7120 | } |
| 7288 | 7121 | ||
| @@ -10945,6 +10778,10 @@ x_initialize () | |||
| 10945 | last_tool_bar_item = -1; | 10778 | last_tool_bar_item = -1; |
| 10946 | any_help_event_p = 0; | 10779 | any_help_event_p = 0; |
| 10947 | 10780 | ||
| 10781 | #ifdef USE_GTK | ||
| 10782 | current_count = -1; | ||
| 10783 | #endif | ||
| 10784 | |||
| 10948 | /* Try to use interrupt input; if we can't, then start polling. */ | 10785 | /* Try to use interrupt input; if we can't, then start polling. */ |
| 10949 | Fset_input_mode (Qt, Qnil, Qt, Qnil); | 10786 | Fset_input_mode (Qt, Qnil, Qt, Qnil); |
| 10950 | 10787 | ||