diff options
| author | Richard M. Stallman | 1997-05-01 01:57:25 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1997-05-01 01:57:25 +0000 |
| commit | e99db5a15cc84acda9f2a94285115bd68c11f507 (patch) | |
| tree | a3b0958f7f5b3c969eacb50665edff297df8d1f2 /src | |
| parent | 610c1c68c1dd1fecd07cabd24d9ea8341e768c74 (diff) | |
| download | emacs-e99db5a15cc84acda9f2a94285115bd68c11f507.tar.gz emacs-e99db5a15cc84acda9f2a94285115bd68c11f507.zip | |
(XTmouse_position, x_term_init):
Save value of x_catch_errors and pass to x_uncatch_errors.
(x_catch_errors): Use specpdl so can be nested.
Use a Lisp string to as the buffer for the X message.
(x_uncatch_errors, x_had_errors_p, x_check_errors): Related changes.
(x_catch_errors_unwind): New function.
(x_error_quitter): Call x_error_catcher if appropriate.
(x_error_message_string): New variable.
(syms_of_xterm): Defvar it.
(x_caught_error_message): Variable deleted.
(X_ERROR_MESSAGE_SIZE): Renamed from X_CAUGHT_ERROR_MESSAGE_SIZE.
(x_error_handler): New function, calls x_error_quitter or ..._checker.
(x_initialize): Use x_error_handler as error handler for X.
Diffstat (limited to 'src')
| -rw-r--r-- | src/xterm.c | 284 |
1 files changed, 159 insertions, 125 deletions
diff --git a/src/xterm.c b/src/xterm.c index 15dbe02a59b..e199af2302d 100644 --- a/src/xterm.c +++ b/src/xterm.c | |||
| @@ -268,7 +268,7 @@ static void do_line_dance (); | |||
| 268 | static int XTcursor_to (); | 268 | static int XTcursor_to (); |
| 269 | static int XTclear_end_of_line (); | 269 | static int XTclear_end_of_line (); |
| 270 | static int x_io_error_quitter (); | 270 | static int x_io_error_quitter (); |
| 271 | void x_catch_errors (); | 271 | int x_catch_errors (); |
| 272 | void x_uncatch_errors (); | 272 | void x_uncatch_errors (); |
| 273 | 273 | ||
| 274 | #if 0 | 274 | #if 0 |
| @@ -2705,6 +2705,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) | |||
| 2705 | Window win, child; | 2705 | Window win, child; |
| 2706 | int win_x, win_y; | 2706 | int win_x, win_y; |
| 2707 | int parent_x, parent_y; | 2707 | int parent_x, parent_y; |
| 2708 | int count; | ||
| 2708 | 2709 | ||
| 2709 | win = root; | 2710 | win = root; |
| 2710 | 2711 | ||
| @@ -2712,7 +2713,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) | |||
| 2712 | structure is changing at the same time this function | 2713 | structure is changing at the same time this function |
| 2713 | is running. So at least we must not crash from them. */ | 2714 | is running. So at least we must not crash from them. */ |
| 2714 | 2715 | ||
| 2715 | x_catch_errors (FRAME_X_DISPLAY (*fp)); | 2716 | count = x_catch_errors (FRAME_X_DISPLAY (*fp)); |
| 2716 | 2717 | ||
| 2717 | if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame | 2718 | if (FRAME_X_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame |
| 2718 | && FRAME_LIVE_P (last_mouse_frame)) | 2719 | && FRAME_LIVE_P (last_mouse_frame)) |
| @@ -2772,7 +2773,7 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time) | |||
| 2772 | if (x_had_errors_p (FRAME_X_DISPLAY (*fp))) | 2773 | if (x_had_errors_p (FRAME_X_DISPLAY (*fp))) |
| 2773 | f1 = 0; | 2774 | f1 = 0; |
| 2774 | 2775 | ||
| 2775 | x_uncatch_errors (FRAME_X_DISPLAY (*fp)); | 2776 | x_uncatch_errors (FRAME_X_DISPLAY (*fp), count); |
| 2776 | 2777 | ||
| 2777 | /* If not, is it one of our scroll bars? */ | 2778 | /* If not, is it one of our scroll bars? */ |
| 2778 | if (! f1) | 2779 | if (! f1) |
| @@ -4938,6 +4939,138 @@ x_text_icon (f, icon_name) | |||
| 4938 | return 0; | 4939 | return 0; |
| 4939 | } | 4940 | } |
| 4940 | 4941 | ||
| 4942 | #define X_ERROR_MESSAGE_SIZE 200 | ||
| 4943 | |||
| 4944 | /* If non-nil, this should be a string. | ||
| 4945 | It means catch X errors and store the error message in this string. */ | ||
| 4946 | |||
| 4947 | static Lisp_Object x_error_message_string; | ||
| 4948 | |||
| 4949 | /* An X error handler which stores the error message in | ||
| 4950 | x_error_message_string. This is called from x_error_handler if | ||
| 4951 | x_catch_errors is in effect. */ | ||
| 4952 | |||
| 4953 | static int | ||
| 4954 | x_error_catcher (display, error) | ||
| 4955 | Display *display; | ||
| 4956 | XErrorEvent *error; | ||
| 4957 | { | ||
| 4958 | XGetErrorText (display, error->error_code, | ||
| 4959 | XSTRING (x_error_message_string)->data, | ||
| 4960 | X_ERROR_MESSAGE_SIZE); | ||
| 4961 | } | ||
| 4962 | |||
| 4963 | /* Begin trapping X errors for display DPY. Actually we trap X errors | ||
| 4964 | for all displays, but DPY should be the display you are actually | ||
| 4965 | operating on. | ||
| 4966 | |||
| 4967 | After calling this function, X protocol errors no longer cause | ||
| 4968 | Emacs to exit; instead, they are recorded in the string | ||
| 4969 | stored in x_error_message_string. | ||
| 4970 | |||
| 4971 | Calling x_check_errors signals an Emacs error if an X error has | ||
| 4972 | occurred since the last call to x_catch_errors or x_check_errors. | ||
| 4973 | |||
| 4974 | Calling x_uncatch_errors resumes the normal error handling. */ | ||
| 4975 | |||
| 4976 | void x_check_errors (); | ||
| 4977 | static Lisp_Object x_catch_errors_unwind (); | ||
| 4978 | |||
| 4979 | int | ||
| 4980 | x_catch_errors (dpy) | ||
| 4981 | Display *dpy; | ||
| 4982 | { | ||
| 4983 | int count = specpdl_ptr - specpdl; | ||
| 4984 | |||
| 4985 | /* Make sure any errors from previous requests have been dealt with. */ | ||
| 4986 | XSync (dpy, False); | ||
| 4987 | |||
| 4988 | record_unwind_protect (x_catch_errors_unwind, x_error_message_string); | ||
| 4989 | |||
| 4990 | x_error_message_string = make_uninit_string (X_ERROR_MESSAGE_SIZE); | ||
| 4991 | XSTRING (x_error_message_string)->data[0] = 0; | ||
| 4992 | |||
| 4993 | return count; | ||
| 4994 | } | ||
| 4995 | |||
| 4996 | /* Unbind the binding that we made to check for X errors. */ | ||
| 4997 | |||
| 4998 | static Lisp_Object | ||
| 4999 | x_catch_errors_unwind (old_val) | ||
| 5000 | Lisp_Object old_val; | ||
| 5001 | { | ||
| 5002 | x_error_message_string = old_val; | ||
| 5003 | return Qnil; | ||
| 5004 | } | ||
| 5005 | |||
| 5006 | /* If any X protocol errors have arrived since the last call to | ||
| 5007 | x_catch_errors or x_check_errors, signal an Emacs error using | ||
| 5008 | sprintf (a buffer, FORMAT, the x error message text) as the text. */ | ||
| 5009 | |||
| 5010 | void | ||
| 5011 | x_check_errors (dpy, format) | ||
| 5012 | Display *dpy; | ||
| 5013 | char *format; | ||
| 5014 | { | ||
| 5015 | /* Make sure to catch any errors incurred so far. */ | ||
| 5016 | XSync (dpy, False); | ||
| 5017 | |||
| 5018 | if (XSTRING (x_error_message_string)->data[0]) | ||
| 5019 | error (format, XSTRING (x_error_message_string)->data); | ||
| 5020 | } | ||
| 5021 | |||
| 5022 | /* Nonzero if we had any X protocol errors on DPY | ||
| 5023 | since we did x_catch_errors. */ | ||
| 5024 | |||
| 5025 | int | ||
| 5026 | x_had_errors_p (dpy) | ||
| 5027 | Display *dpy; | ||
| 5028 | { | ||
| 5029 | /* Make sure to catch any errors incurred so far. */ | ||
| 5030 | XSync (dpy, False); | ||
| 5031 | |||
| 5032 | return XSTRING (x_error_message_string)->data[0] != 0; | ||
| 5033 | } | ||
| 5034 | |||
| 5035 | /* Stop catching X protocol errors and let them make Emacs die. | ||
| 5036 | DPY should be the display that was passed to x_catch_errors. | ||
| 5037 | COUNT should be the value that was returned by | ||
| 5038 | the corresponding call to x_catch_errors. */ | ||
| 5039 | |||
| 5040 | void | ||
| 5041 | x_uncatch_errors (dpy, count) | ||
| 5042 | Display *dpy; | ||
| 5043 | int count; | ||
| 5044 | { | ||
| 5045 | unbind_to (count, Qnil); | ||
| 5046 | } | ||
| 5047 | |||
| 5048 | #if 0 | ||
| 5049 | static unsigned int x_wire_count; | ||
| 5050 | x_trace_wire () | ||
| 5051 | { | ||
| 5052 | fprintf (stderr, "Lib call: %d\n", ++x_wire_count); | ||
| 5053 | } | ||
| 5054 | #endif /* ! 0 */ | ||
| 5055 | |||
| 5056 | |||
| 5057 | /* Handle SIGPIPE, which can happen when the connection to a server | ||
| 5058 | simply goes away. SIGPIPE is handled by x_connection_signal. | ||
| 5059 | Don't need to do anything, because the write which caused the | ||
| 5060 | SIGPIPE will fail, causing Xlib to invoke the X IO error handler, | ||
| 5061 | which will do the appropriate cleanup for us. */ | ||
| 5062 | |||
| 5063 | static SIGTYPE | ||
| 5064 | x_connection_signal (signalnum) /* If we don't have an argument, */ | ||
| 5065 | int signalnum; /* some compilers complain in signal calls. */ | ||
| 5066 | { | ||
| 5067 | #ifdef USG | ||
| 5068 | /* USG systems forget handlers when they are used; | ||
| 5069 | must reestablish each time */ | ||
| 5070 | signal (signalnum, x_connection_signal); | ||
| 5071 | #endif /* USG */ | ||
| 5072 | } | ||
| 5073 | |||
| 4941 | /* Handling X errors. */ | 5074 | /* Handling X errors. */ |
| 4942 | 5075 | ||
| 4943 | /* Handle the loss of connection to display DISPLAY. */ | 5076 | /* Handle the loss of connection to display DISPLAY. */ |
| @@ -5026,138 +5159,35 @@ x_error_quitter (display, error) | |||
| 5026 | x_connection_closed (display, buf1); | 5159 | x_connection_closed (display, buf1); |
| 5027 | } | 5160 | } |
| 5028 | 5161 | ||
| 5029 | /* This is the handler for X IO errors, always. | 5162 | /* This is the first-level handler for X protocol errors. |
| 5030 | It kills all frames on the display that we lost touch with. | 5163 | It calls x_error_quitter or x_error_catcher. */ |
| 5031 | If that was the only one, it prints an error message and kills Emacs. */ | ||
| 5032 | 5164 | ||
| 5033 | static int | 5165 | static int |
| 5034 | x_io_error_quitter (display) | 5166 | x_error_handler (display, error) |
| 5035 | Display *display; | 5167 | Display *display; |
| 5168 | XErrorEvent *error; | ||
| 5036 | { | 5169 | { |
| 5037 | char buf[256]; | 5170 | char buf[256], buf1[356]; |
| 5038 | 5171 | ||
| 5039 | sprintf (buf, "Connection lost to X server `%s'", DisplayString (display)); | 5172 | if (! NILP (x_error_message_string)) |
| 5040 | x_connection_closed (display, buf); | 5173 | x_error_catcher (display, error); |
| 5041 | } | 5174 | else |
| 5042 | 5175 | x_error_quitter (display, error); | |
| 5043 | /* Handle SIGPIPE, which can happen when the connection to a server | ||
| 5044 | simply goes away. SIGPIPE is handled by x_connection_signal. | ||
| 5045 | Don't need to do anything, because the write which caused the | ||
| 5046 | SIGPIPE will fail, causing Xlib to invoke the X IO error handler, | ||
| 5047 | which will do the appropriate cleanup for us. */ | ||
| 5048 | |||
| 5049 | static SIGTYPE | ||
| 5050 | x_connection_signal (signalnum) /* If we don't have an argument, */ | ||
| 5051 | int signalnum; /* some compilers complain in signal calls. */ | ||
| 5052 | { | ||
| 5053 | #ifdef USG | ||
| 5054 | /* USG systems forget handlers when they are used; | ||
| 5055 | must reestablish each time */ | ||
| 5056 | signal (signalnum, x_connection_signal); | ||
| 5057 | #endif /* USG */ | ||
| 5058 | } | 5176 | } |
| 5059 | |||
| 5060 | /* A buffer for storing X error messages. */ | ||
| 5061 | static char *x_caught_error_message; | ||
| 5062 | #define X_CAUGHT_ERROR_MESSAGE_SIZE 200 | ||
| 5063 | 5177 | ||
| 5064 | /* An X error handler which stores the error message in | 5178 | /* This is the handler for X IO errors, always. |
| 5065 | x_caught_error_message. This is what's installed when | 5179 | It kills all frames on the display that we lost touch with. |
| 5066 | x_catch_errors is in effect. */ | 5180 | If that was the only one, it prints an error message and kills Emacs. */ |
| 5067 | 5181 | ||
| 5068 | static int | 5182 | static int |
| 5069 | x_error_catcher (display, error) | 5183 | x_io_error_quitter (display) |
| 5070 | Display *display; | 5184 | Display *display; |
| 5071 | XErrorEvent *error; | ||
| 5072 | { | ||
| 5073 | XGetErrorText (display, error->error_code, | ||
| 5074 | x_caught_error_message, X_CAUGHT_ERROR_MESSAGE_SIZE); | ||
| 5075 | } | ||
| 5076 | |||
| 5077 | |||
| 5078 | /* Begin trapping X errors for display DPY. Actually we trap X errors | ||
| 5079 | for all displays, but DPY should be the display you are actually | ||
| 5080 | operating on. | ||
| 5081 | |||
| 5082 | After calling this function, X protocol errors no longer cause | ||
| 5083 | Emacs to exit; instead, they are recorded in x_cfc_error_message. | ||
| 5084 | |||
| 5085 | Calling x_check_errors signals an Emacs error if an X error has | ||
| 5086 | occurred since the last call to x_catch_errors or x_check_errors. | ||
| 5087 | |||
| 5088 | Calling x_uncatch_errors resumes the normal error handling. */ | ||
| 5089 | |||
| 5090 | void x_catch_errors (), x_check_errors (), x_uncatch_errors (); | ||
| 5091 | |||
| 5092 | void | ||
| 5093 | x_catch_errors (dpy) | ||
| 5094 | Display *dpy; | ||
| 5095 | { | ||
| 5096 | /* Make sure any errors from previous requests have been dealt with. */ | ||
| 5097 | XSync (dpy, False); | ||
| 5098 | |||
| 5099 | /* Set up the error buffer. */ | ||
| 5100 | x_caught_error_message | ||
| 5101 | = (char*) xmalloc (X_CAUGHT_ERROR_MESSAGE_SIZE); | ||
| 5102 | x_caught_error_message[0] = '\0'; | ||
| 5103 | |||
| 5104 | /* Install our little error handler. */ | ||
| 5105 | XSetErrorHandler (x_error_catcher); | ||
| 5106 | } | ||
| 5107 | |||
| 5108 | /* If any X protocol errors have arrived since the last call to | ||
| 5109 | x_catch_errors or x_check_errors, signal an Emacs error using | ||
| 5110 | sprintf (a buffer, FORMAT, the x error message text) as the text. */ | ||
| 5111 | |||
| 5112 | void | ||
| 5113 | x_check_errors (dpy, format) | ||
| 5114 | Display *dpy; | ||
| 5115 | char *format; | ||
| 5116 | { | 5185 | { |
| 5117 | /* Make sure to catch any errors incurred so far. */ | 5186 | char buf[256]; |
| 5118 | XSync (dpy, False); | ||
| 5119 | |||
| 5120 | if (x_caught_error_message[0]) | ||
| 5121 | { | ||
| 5122 | char buf[X_CAUGHT_ERROR_MESSAGE_SIZE + 56]; | ||
| 5123 | |||
| 5124 | sprintf (buf, format, x_caught_error_message); | ||
| 5125 | x_uncatch_errors (dpy); | ||
| 5126 | error (buf); | ||
| 5127 | } | ||
| 5128 | } | ||
| 5129 | |||
| 5130 | /* Nonzero if we had any X protocol errors since we did x_catch_errors. */ | ||
| 5131 | |||
| 5132 | int | ||
| 5133 | x_had_errors_p (dpy) | ||
| 5134 | Display *dpy; | ||
| 5135 | { | ||
| 5136 | /* Make sure to catch any errors incurred so far. */ | ||
| 5137 | XSync (dpy, False); | ||
| 5138 | |||
| 5139 | return x_caught_error_message[0] != 0; | ||
| 5140 | } | ||
| 5141 | |||
| 5142 | /* Stop catching X protocol errors and let them make Emacs die. */ | ||
| 5143 | |||
| 5144 | void | ||
| 5145 | x_uncatch_errors (dpy) | ||
| 5146 | Display *dpy; | ||
| 5147 | { | ||
| 5148 | xfree (x_caught_error_message); | ||
| 5149 | x_caught_error_message = 0; | ||
| 5150 | XSetErrorHandler (x_error_quitter); | ||
| 5151 | } | ||
| 5152 | 5187 | ||
| 5153 | #if 0 | 5188 | sprintf (buf, "Connection lost to X server `%s'", DisplayString (display)); |
| 5154 | static unsigned int x_wire_count; | 5189 | x_connection_closed (display, buf); |
| 5155 | x_trace_wire () | ||
| 5156 | { | ||
| 5157 | fprintf (stderr, "Lib call: %d\n", ++x_wire_count); | ||
| 5158 | } | 5190 | } |
| 5159 | #endif /* ! 0 */ | ||
| 5160 | |||
| 5161 | 5191 | ||
| 5162 | /* Changing the font of the frame. */ | 5192 | /* Changing the font of the frame. */ |
| 5163 | 5193 | ||
| @@ -6831,6 +6861,7 @@ x_term_init (display_name, xrm_option, resource_name) | |||
| 6831 | Display *dpy = dpyinfo->display; | 6861 | Display *dpy = dpyinfo->display; |
| 6832 | XrmValue d, fr, to; | 6862 | XrmValue d, fr, to; |
| 6833 | Font font; | 6863 | Font font; |
| 6864 | int count; | ||
| 6834 | 6865 | ||
| 6835 | d.addr = (XPointer)&dpy; | 6866 | d.addr = (XPointer)&dpy; |
| 6836 | d.size = sizeof (Display *); | 6867 | d.size = sizeof (Display *); |
| @@ -6838,12 +6869,12 @@ x_term_init (display_name, xrm_option, resource_name) | |||
| 6838 | fr.size = sizeof (XtDefaultFont); | 6869 | fr.size = sizeof (XtDefaultFont); |
| 6839 | to.size = sizeof (Font *); | 6870 | to.size = sizeof (Font *); |
| 6840 | to.addr = (XPointer)&font; | 6871 | to.addr = (XPointer)&font; |
| 6841 | x_catch_errors (dpy); | 6872 | count = x_catch_errors (dpy); |
| 6842 | if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL)) | 6873 | if (!XtCallConverter (dpy, XtCvtStringToFont, &d, 1, &fr, &to, NULL)) |
| 6843 | abort (); | 6874 | abort (); |
| 6844 | if (x_had_errors_p (dpy) || !XQueryFont (dpy, font)) | 6875 | if (x_had_errors_p (dpy) || !XQueryFont (dpy, font)) |
| 6845 | XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15"); | 6876 | XrmPutLineResource (&xrdb, "Emacs.dialog.*.font: 9x15"); |
| 6846 | x_uncatch_errors (dpy); | 6877 | x_uncatch_errors (dpy, count); |
| 6847 | } | 6878 | } |
| 6848 | #endif | 6879 | #endif |
| 6849 | 6880 | ||
| @@ -6959,7 +6990,7 @@ x_initialize () | |||
| 6959 | 6990 | ||
| 6960 | /* Note that there is no real way portable across R3/R4 to get the | 6991 | /* Note that there is no real way portable across R3/R4 to get the |
| 6961 | original error handler. */ | 6992 | original error handler. */ |
| 6962 | XSetErrorHandler (x_error_quitter); | 6993 | XSetErrorHandler (x_error_handler); |
| 6963 | XSetIOErrorHandler (x_io_error_quitter); | 6994 | XSetIOErrorHandler (x_io_error_quitter); |
| 6964 | 6995 | ||
| 6965 | /* Disable Window Change signals; they are handled by X events. */ | 6996 | /* Disable Window Change signals; they are handled by X events. */ |
| @@ -6973,6 +7004,9 @@ x_initialize () | |||
| 6973 | void | 7004 | void |
| 6974 | syms_of_xterm () | 7005 | syms_of_xterm () |
| 6975 | { | 7006 | { |
| 7007 | staticpro (&x_error_message_string); | ||
| 7008 | x_error_message_string = Qnil; | ||
| 7009 | |||
| 6976 | staticpro (&x_display_name_list); | 7010 | staticpro (&x_display_name_list); |
| 6977 | x_display_name_list = Qnil; | 7011 | x_display_name_list = Qnil; |
| 6978 | 7012 | ||