diff options
Diffstat (limited to 'src/mac.c')
| -rw-r--r-- | src/mac.c | 463 |
1 files changed, 248 insertions, 215 deletions
| @@ -2413,75 +2413,69 @@ sys_fopen (const char *name, const char *mode) | |||
| 2413 | } | 2413 | } |
| 2414 | 2414 | ||
| 2415 | 2415 | ||
| 2416 | #include "keyboard.h" | 2416 | extern Boolean mac_wait_next_event P_ ((EventRecord *, UInt32, Boolean)); |
| 2417 | extern Boolean mac_wait_next_event (EventRecord *, UInt32, Boolean); | ||
| 2418 | 2417 | ||
| 2419 | int | 2418 | int |
| 2420 | select (n, rfds, wfds, efds, timeout) | 2419 | select (nfds, rfds, wfds, efds, timeout) |
| 2421 | int n; | 2420 | int nfds; |
| 2422 | SELECT_TYPE *rfds; | 2421 | SELECT_TYPE *rfds, *wfds, *efds; |
| 2423 | SELECT_TYPE *wfds; | 2422 | EMACS_TIME *timeout; |
| 2424 | SELECT_TYPE *efds; | ||
| 2425 | struct timeval *timeout; | ||
| 2426 | { | 2423 | { |
| 2427 | OSStatus err; | 2424 | OSStatus err = noErr; |
| 2428 | #if TARGET_API_MAC_CARBON | ||
| 2429 | EventTimeout timeout_sec = | ||
| 2430 | (timeout | ||
| 2431 | ? (EMACS_SECS (*timeout) * kEventDurationSecond | ||
| 2432 | + EMACS_USECS (*timeout) * kEventDurationMicrosecond) | ||
| 2433 | : kEventDurationForever); | ||
| 2434 | |||
| 2435 | BLOCK_INPUT; | ||
| 2436 | err = ReceiveNextEvent (0, NULL, timeout_sec, kEventLeaveInQueue, NULL); | ||
| 2437 | UNBLOCK_INPUT; | ||
| 2438 | #else /* not TARGET_API_MAC_CARBON */ | ||
| 2439 | EventRecord e; | ||
| 2440 | UInt32 sleep_time = EMACS_SECS (*timeout) * 60 + | ||
| 2441 | ((EMACS_USECS (*timeout) * 60) / 1000000); | ||
| 2442 | 2425 | ||
| 2443 | /* Can only handle wait for keyboard input. */ | 2426 | /* Can only handle wait for keyboard input. */ |
| 2444 | if (n > 1 || wfds || efds) | 2427 | if (nfds > 1 || wfds || efds) |
| 2445 | return -1; | 2428 | return -1; |
| 2446 | 2429 | ||
| 2447 | /* Also return true if an event other than a keyDown has occurred. | 2430 | /* Try detect_input_pending before ReceiveNextEvent in the same |
| 2448 | This causes kbd_buffer_get_event in keyboard.c to call | 2431 | BLOCK_INPUT block, in case that some input has already been read |
| 2449 | read_avail_input which in turn calls XTread_socket to poll for | 2432 | asynchronously. */ |
| 2450 | these events. Otherwise these never get processed except but a | 2433 | BLOCK_INPUT; |
| 2451 | very slow poll timer. */ | 2434 | if (!detect_input_pending ()) |
| 2452 | if (mac_wait_next_event (&e, sleep_time, false)) | 2435 | { |
| 2453 | err = noErr; | 2436 | #if TARGET_API_MAC_CARBON |
| 2454 | else | 2437 | EventTimeout timeoutval = |
| 2455 | err = -9875; /* eventLoopTimedOutErr */ | 2438 | (timeout |
| 2439 | ? (EMACS_SECS (*timeout) * kEventDurationSecond | ||
| 2440 | + EMACS_USECS (*timeout) * kEventDurationMicrosecond) | ||
| 2441 | : kEventDurationForever); | ||
| 2442 | |||
| 2443 | if (timeoutval == 0.0) | ||
| 2444 | err = eventLoopTimedOutErr; | ||
| 2445 | else | ||
| 2446 | err = ReceiveNextEvent (0, NULL, timeoutval, | ||
| 2447 | kEventLeaveInQueue, NULL); | ||
| 2448 | #else /* not TARGET_API_MAC_CARBON */ | ||
| 2449 | EventRecord e; | ||
| 2450 | UInt32 sleep_time = EMACS_SECS (*timeout) * 60 + | ||
| 2451 | ((EMACS_USECS (*timeout) * 60) / 1000000); | ||
| 2452 | |||
| 2453 | if (sleep_time == 0) | ||
| 2454 | err = -9875; /* eventLoopTimedOutErr */ | ||
| 2455 | else | ||
| 2456 | { | ||
| 2457 | if (mac_wait_next_event (&e, sleep_time, false)) | ||
| 2458 | err = noErr; | ||
| 2459 | else | ||
| 2460 | err = -9875; /* eventLoopTimedOutErr */ | ||
| 2461 | } | ||
| 2456 | #endif /* not TARGET_API_MAC_CARBON */ | 2462 | #endif /* not TARGET_API_MAC_CARBON */ |
| 2463 | } | ||
| 2464 | UNBLOCK_INPUT; | ||
| 2457 | 2465 | ||
| 2458 | if (FD_ISSET (0, rfds)) | 2466 | if (err == noErr) |
| 2459 | if (err == noErr) | 2467 | { |
| 2460 | return 1; | 2468 | /* Pretend that `select' is interrupted by a signal. */ |
| 2461 | else | 2469 | detect_input_pending (); |
| 2462 | { | 2470 | errno = EINTR; |
| 2463 | FD_ZERO (rfds); | 2471 | return -1; |
| 2464 | return 0; | 2472 | } |
| 2465 | } | ||
| 2466 | else | 2473 | else |
| 2467 | if (err == noErr) | 2474 | { |
| 2468 | { | 2475 | if (rfds) |
| 2469 | if (input_polling_used ()) | 2476 | FD_ZERO (rfds); |
| 2470 | { | ||
| 2471 | /* It could be confusing if a real alarm arrives while | ||
| 2472 | processing the fake one. Turn it off and let the | ||
| 2473 | handler reset it. */ | ||
| 2474 | extern void poll_for_input_1 P_ ((void)); | ||
| 2475 | int old_poll_suppress_count = poll_suppress_count; | ||
| 2476 | poll_suppress_count = 1; | ||
| 2477 | poll_for_input_1 (); | ||
| 2478 | poll_suppress_count = old_poll_suppress_count; | ||
| 2479 | } | ||
| 2480 | errno = EINTR; | ||
| 2481 | return -1; | ||
| 2482 | } | ||
| 2483 | else | ||
| 2484 | return 0; | 2477 | return 0; |
| 2478 | } | ||
| 2485 | } | 2479 | } |
| 2486 | 2480 | ||
| 2487 | 2481 | ||
| @@ -4904,6 +4898,30 @@ On successful conversion, return the result string, else return nil. */) | |||
| 4904 | 4898 | ||
| 4905 | return result; | 4899 | return result; |
| 4906 | } | 4900 | } |
| 4901 | |||
| 4902 | DEFUN ("mac-process-hi-command", Fmac_process_hi_command, Smac_process_hi_command, 1, 1, 0, | ||
| 4903 | doc: /* Send a HI command whose ID is COMMAND-ID to the command chain. | ||
| 4904 | COMMAND-ID must be a 4-character string. Some common command IDs are | ||
| 4905 | defined in the Carbon Event Manager. */) | ||
| 4906 | (command_id) | ||
| 4907 | Lisp_Object command_id; | ||
| 4908 | { | ||
| 4909 | OSStatus err; | ||
| 4910 | HICommand command; | ||
| 4911 | |||
| 4912 | bzero (&command, sizeof (HICommand)); | ||
| 4913 | command.commandID = mac_get_code_from_arg (command_id, 0); | ||
| 4914 | |||
| 4915 | BLOCK_INPUT; | ||
| 4916 | err = ProcessHICommand (&command); | ||
| 4917 | UNBLOCK_INPUT; | ||
| 4918 | |||
| 4919 | if (err != noErr) | ||
| 4920 | error ("HI command (command ID: '%s') not handled.", SDATA (command_id)); | ||
| 4921 | |||
| 4922 | return Qnil; | ||
| 4923 | } | ||
| 4924 | |||
| 4907 | #endif /* TARGET_API_MAC_CARBON */ | 4925 | #endif /* TARGET_API_MAC_CARBON */ |
| 4908 | 4926 | ||
| 4909 | 4927 | ||
| @@ -4944,23 +4962,26 @@ extern int noninteractive; | |||
| 4944 | -> Use `select'. | 4962 | -> Use `select'. |
| 4945 | 2. Sockets are not involved. | 4963 | 2. Sockets are not involved. |
| 4946 | -> Use ReceiveNextEvent. | 4964 | -> Use ReceiveNextEvent. |
| 4947 | 3. [If SELECT_USE_CFSOCKET is defined] | 4965 | 3. [If SELECT_USE_CFSOCKET is set] |
| 4948 | Only the window event channel and socket read channels are | 4966 | Only the window event channel and socket read/write channels are |
| 4949 | involved, and timeout is not too short (greater than | 4967 | involved, and timeout is not too short (greater than |
| 4950 | SELECT_TIMEOUT_THRESHHOLD_RUNLOOP seconds). | 4968 | SELECT_TIMEOUT_THRESHHOLD_RUNLOOP seconds). |
| 4951 | -> Create CFSocket for each socket and add it into the current | 4969 | -> Create CFSocket for each socket and add it into the current |
| 4952 | event RunLoop so that a `ready-to-read' event can be posted | 4970 | event RunLoop so that the current event loop gets quit when |
| 4953 | to the event queue that is also used for window events. Then | 4971 | the socket becomes ready. Then ReceiveNextEvent can wait for |
| 4954 | ReceiveNextEvent can wait for both kinds of inputs. | 4972 | both kinds of inputs. |
| 4955 | 4. Otherwise. | 4973 | 4. Otherwise. |
| 4956 | -> Periodically poll the window input channel while repeatedly | 4974 | -> Periodically poll the window input channel while repeatedly |
| 4957 | executing `select' with a short timeout | 4975 | executing `select' with a short timeout |
| 4958 | (SELECT_POLLING_PERIOD_USEC microseconds). */ | 4976 | (SELECT_POLLING_PERIOD_USEC microseconds). */ |
| 4959 | 4977 | ||
| 4960 | #define SELECT_POLLING_PERIOD_USEC 20000 | 4978 | #ifndef SELECT_USE_CFSOCKET |
| 4961 | #ifdef SELECT_USE_CFSOCKET | 4979 | #define SELECT_USE_CFSOCKET 1 |
| 4980 | #endif | ||
| 4981 | |||
| 4982 | #define SELECT_POLLING_PERIOD_USEC 100000 | ||
| 4983 | #if SELECT_USE_CFSOCKET | ||
| 4962 | #define SELECT_TIMEOUT_THRESHOLD_RUNLOOP 0.2 | 4984 | #define SELECT_TIMEOUT_THRESHOLD_RUNLOOP 0.2 |
| 4963 | #define EVENT_CLASS_SOCK 'Sock' | ||
| 4964 | 4985 | ||
| 4965 | static void | 4986 | static void |
| 4966 | socket_callback (s, type, address, data, info) | 4987 | socket_callback (s, type, address, data, info) |
| @@ -4970,196 +4991,211 @@ socket_callback (s, type, address, data, info) | |||
| 4970 | const void *data; | 4991 | const void *data; |
| 4971 | void *info; | 4992 | void *info; |
| 4972 | { | 4993 | { |
| 4973 | EventRef event; | 4994 | int fd = CFSocketGetNative (s); |
| 4995 | SELECT_TYPE *ofds = (SELECT_TYPE *)info; | ||
| 4974 | 4996 | ||
| 4975 | CreateEvent (NULL, EVENT_CLASS_SOCK, 0, 0, kEventAttributeNone, &event); | 4997 | if ((type == kCFSocketReadCallBack && FD_ISSET (fd, &ofds[0])) |
| 4976 | PostEventToQueue (GetCurrentEventQueue (), event, kEventPriorityStandard); | 4998 | || (type == kCFSocketConnectCallBack && FD_ISSET (fd, &ofds[1]))) |
| 4977 | ReleaseEvent (event); | 4999 | QuitEventLoop (GetCurrentEventLoop ()); |
| 4978 | } | 5000 | } |
| 4979 | #endif /* SELECT_USE_CFSOCKET */ | 5001 | #endif /* SELECT_USE_CFSOCKET */ |
| 4980 | 5002 | ||
| 4981 | static int | 5003 | static int |
| 4982 | select_and_poll_event (n, rfds, wfds, efds, timeout) | 5004 | select_and_poll_event (nfds, rfds, wfds, efds, timeout) |
| 4983 | int n; | 5005 | int nfds; |
| 4984 | SELECT_TYPE *rfds; | 5006 | SELECT_TYPE *rfds, *wfds, *efds; |
| 4985 | SELECT_TYPE *wfds; | 5007 | EMACS_TIME *timeout; |
| 4986 | SELECT_TYPE *efds; | ||
| 4987 | struct timeval *timeout; | ||
| 4988 | { | 5008 | { |
| 4989 | int r; | 5009 | OSStatus err = noErr; |
| 4990 | OSStatus err; | 5010 | int r = 0; |
| 4991 | 5011 | ||
| 4992 | r = select (n, rfds, wfds, efds, timeout); | 5012 | /* Try detect_input_pending before ReceiveNextEvent in the same |
| 4993 | if (r != -1) | 5013 | BLOCK_INPUT block, in case that some input has already been read |
| 5014 | asynchronously. */ | ||
| 5015 | BLOCK_INPUT; | ||
| 5016 | if (!detect_input_pending ()) | ||
| 4994 | { | 5017 | { |
| 4995 | BLOCK_INPUT; | 5018 | EMACS_TIME select_timeout; |
| 4996 | err = ReceiveNextEvent (0, NULL, kEventDurationNoWait, | 5019 | EventTimeout timeoutval = |
| 4997 | kEventLeaveInQueue, NULL); | 5020 | (timeout |
| 4998 | UNBLOCK_INPUT; | 5021 | ? (EMACS_SECS (*timeout) * kEventDurationSecond |
| 4999 | if (err == noErr) | 5022 | + EMACS_USECS (*timeout) * kEventDurationMicrosecond) |
| 5023 | : kEventDurationForever); | ||
| 5024 | |||
| 5025 | EMACS_SET_SECS_USECS (select_timeout, 0, 0); | ||
| 5026 | r = select (nfds, rfds, wfds, efds, &select_timeout); | ||
| 5027 | if (timeoutval == 0.0) | ||
| 5028 | err = eventLoopTimedOutErr; | ||
| 5029 | else if (r == 0) | ||
| 5000 | { | 5030 | { |
| 5001 | FD_SET (0, rfds); | 5031 | #if USE_CG_DRAWING |
| 5002 | r++; | 5032 | mac_prepare_for_quickdraw (NULL); |
| 5033 | #endif | ||
| 5034 | err = ReceiveNextEvent (0, NULL, timeoutval, | ||
| 5035 | kEventLeaveInQueue, NULL); | ||
| 5003 | } | 5036 | } |
| 5004 | } | 5037 | } |
| 5005 | return r; | 5038 | UNBLOCK_INPUT; |
| 5006 | } | ||
| 5007 | 5039 | ||
| 5008 | #if MAC_OS_X_VERSION_MAX_ALLOWED < 1020 | 5040 | if (r != 0) |
| 5009 | #undef SELECT_INVALIDATE_CFSOCKET | 5041 | return r; |
| 5010 | #endif | 5042 | else if (err == noErr) |
| 5043 | { | ||
| 5044 | /* Pretend that `select' is interrupted by a signal. */ | ||
| 5045 | detect_input_pending (); | ||
| 5046 | errno = EINTR; | ||
| 5047 | return -1; | ||
| 5048 | } | ||
| 5049 | else | ||
| 5050 | return 0; | ||
| 5051 | } | ||
| 5011 | 5052 | ||
| 5012 | int | 5053 | int |
| 5013 | sys_select (n, rfds, wfds, efds, timeout) | 5054 | sys_select (nfds, rfds, wfds, efds, timeout) |
| 5014 | int n; | 5055 | int nfds; |
| 5015 | SELECT_TYPE *rfds; | 5056 | SELECT_TYPE *rfds, *wfds, *efds; |
| 5016 | SELECT_TYPE *wfds; | 5057 | EMACS_TIME *timeout; |
| 5017 | SELECT_TYPE *efds; | ||
| 5018 | struct timeval *timeout; | ||
| 5019 | { | 5058 | { |
| 5020 | OSStatus err; | 5059 | OSStatus err = noErr; |
| 5021 | int i, r; | 5060 | int r; |
| 5022 | EMACS_TIME select_timeout; | 5061 | EMACS_TIME select_timeout; |
| 5062 | static SELECT_TYPE ofds[3]; | ||
| 5023 | 5063 | ||
| 5024 | if (inhibit_window_system || noninteractive | 5064 | if (inhibit_window_system || noninteractive |
| 5025 | || rfds == NULL || !FD_ISSET (0, rfds)) | 5065 | || nfds < 1 || rfds == NULL || !FD_ISSET (0, rfds)) |
| 5026 | return select (n, rfds, wfds, efds, timeout); | 5066 | return select (nfds, rfds, wfds, efds, timeout); |
| 5027 | 5067 | ||
| 5028 | FD_CLR (0, rfds); | 5068 | FD_CLR (0, rfds); |
| 5069 | ofds[0] = *rfds; | ||
| 5029 | 5070 | ||
| 5030 | if (wfds == NULL && efds == NULL) | 5071 | if (wfds) |
| 5031 | { | 5072 | ofds[1] = *wfds; |
| 5032 | int nsocks = 0; | 5073 | else |
| 5033 | SELECT_TYPE orfds = *rfds; | 5074 | FD_ZERO (&ofds[1]); |
| 5034 | 5075 | ||
| 5035 | EventTimeout timeout_sec = | 5076 | if (efds) |
| 5077 | ofds[2] = *efds; | ||
| 5078 | else | ||
| 5079 | { | ||
| 5080 | EventTimeout timeoutval = | ||
| 5036 | (timeout | 5081 | (timeout |
| 5037 | ? (EMACS_SECS (*timeout) * kEventDurationSecond | 5082 | ? (EMACS_SECS (*timeout) * kEventDurationSecond |
| 5038 | + EMACS_USECS (*timeout) * kEventDurationMicrosecond) | 5083 | + EMACS_USECS (*timeout) * kEventDurationMicrosecond) |
| 5039 | : kEventDurationForever); | 5084 | : kEventDurationForever); |
| 5040 | 5085 | ||
| 5041 | for (i = 1; i < n; i++) | 5086 | FD_SET (0, rfds); /* sentinel */ |
| 5042 | if (FD_ISSET (i, rfds)) | 5087 | do |
| 5043 | nsocks++; | ||
| 5044 | |||
| 5045 | if (nsocks == 0) | ||
| 5046 | { | 5088 | { |
| 5047 | BLOCK_INPUT; | 5089 | nfds--; |
| 5048 | err = ReceiveNextEvent (0, NULL, timeout_sec, | ||
| 5049 | kEventLeaveInQueue, NULL); | ||
| 5050 | UNBLOCK_INPUT; | ||
| 5051 | if (err == noErr) | ||
| 5052 | { | ||
| 5053 | FD_SET (0, rfds); | ||
| 5054 | return 1; | ||
| 5055 | } | ||
| 5056 | else | ||
| 5057 | return 0; | ||
| 5058 | } | 5090 | } |
| 5091 | while (!(FD_ISSET (nfds, rfds) || (wfds && FD_ISSET (nfds, wfds)))); | ||
| 5092 | nfds++; | ||
| 5093 | FD_CLR (0, rfds); | ||
| 5094 | |||
| 5095 | if (nfds == 1) | ||
| 5096 | return select_and_poll_event (nfds, rfds, wfds, efds, timeout); | ||
| 5059 | 5097 | ||
| 5060 | #if USE_CG_DRAWING | ||
| 5061 | mac_prepare_for_quickdraw (NULL); | ||
| 5062 | #endif | ||
| 5063 | /* Avoid initial overhead of RunLoop setup for the case that | 5098 | /* Avoid initial overhead of RunLoop setup for the case that |
| 5064 | some input is already available. */ | 5099 | some input is already available. */ |
| 5065 | EMACS_SET_SECS_USECS (select_timeout, 0, 0); | 5100 | EMACS_SET_SECS_USECS (select_timeout, 0, 0); |
| 5066 | r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout); | 5101 | r = select_and_poll_event (nfds, rfds, wfds, efds, &select_timeout); |
| 5067 | if (r != 0 || timeout_sec == 0.0) | 5102 | if (r != 0 || timeoutval == 0.0) |
| 5068 | return r; | 5103 | return r; |
| 5069 | 5104 | ||
| 5070 | *rfds = orfds; | 5105 | *rfds = ofds[0]; |
| 5106 | if (wfds) | ||
| 5107 | *wfds = ofds[1]; | ||
| 5071 | 5108 | ||
| 5072 | #ifdef SELECT_USE_CFSOCKET | 5109 | #if SELECT_USE_CFSOCKET |
| 5073 | if (timeout_sec > 0 && timeout_sec <= SELECT_TIMEOUT_THRESHOLD_RUNLOOP) | 5110 | if (timeoutval > 0 && timeoutval <= SELECT_TIMEOUT_THRESHOLD_RUNLOOP) |
| 5074 | goto poll_periodically; | 5111 | goto poll_periodically; |
| 5075 | 5112 | ||
| 5076 | { | 5113 | /* Try detect_input_pending before ReceiveNextEvent in the same |
| 5077 | CFRunLoopRef runloop = | 5114 | BLOCK_INPUT block, in case that some input has already been |
| 5078 | (CFRunLoopRef) GetCFRunLoopFromEventLoop (GetCurrentEventLoop ()); | 5115 | read asynchronously. */ |
| 5079 | EventTypeSpec specs[] = {{EVENT_CLASS_SOCK, 0}}; | 5116 | BLOCK_INPUT; |
| 5080 | #ifdef SELECT_INVALIDATE_CFSOCKET | 5117 | if (!detect_input_pending ()) |
| 5081 | CFSocketRef *shead, *s; | 5118 | { |
| 5082 | #else | 5119 | int minfd, fd; |
| 5083 | CFRunLoopSourceRef *shead, *s; | 5120 | CFRunLoopRef runloop = |
| 5084 | #endif | 5121 | (CFRunLoopRef) GetCFRunLoopFromEventLoop (GetCurrentEventLoop ()); |
| 5085 | 5122 | static CFSocketContext context = {0, ofds, NULL, NULL, NULL}; | |
| 5086 | BLOCK_INPUT; | 5123 | static CFMutableDictionaryRef sources; |
| 5087 | 5124 | ||
| 5088 | #ifdef SELECT_INVALIDATE_CFSOCKET | 5125 | if (sources == NULL) |
| 5089 | shead = xmalloc (sizeof (CFSocketRef) * nsocks); | 5126 | sources = |
| 5090 | #else | 5127 | CFDictionaryCreateMutable (NULL, 0, NULL, |
| 5091 | shead = xmalloc (sizeof (CFRunLoopSourceRef) * nsocks); | 5128 | &kCFTypeDictionaryValueCallBacks); |
| 5092 | #endif | 5129 | |
| 5093 | s = shead; | 5130 | for (minfd = 1; ; minfd++) /* nfds-1 works as a sentinel. */ |
| 5094 | for (i = 1; i < n; i++) | 5131 | if (FD_ISSET (minfd, rfds) || (wfds && FD_ISSET (minfd, wfds))) |
| 5095 | if (FD_ISSET (i, rfds)) | 5132 | break; |
| 5096 | { | ||
| 5097 | CFSocketRef socket = | ||
| 5098 | CFSocketCreateWithNative (NULL, i, kCFSocketReadCallBack, | ||
| 5099 | socket_callback, NULL); | ||
| 5100 | CFRunLoopSourceRef source = | ||
| 5101 | CFSocketCreateRunLoopSource (NULL, socket, 0); | ||
| 5102 | |||
| 5103 | #ifdef SELECT_INVALIDATE_CFSOCKET | ||
| 5104 | CFSocketSetSocketFlags (socket, 0); | ||
| 5105 | #endif | ||
| 5106 | CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode); | ||
| 5107 | #ifdef SELECT_INVALIDATE_CFSOCKET | ||
| 5108 | CFRelease (source); | ||
| 5109 | *s = socket; | ||
| 5110 | #else | ||
| 5111 | CFRelease (socket); | ||
| 5112 | *s = source; | ||
| 5113 | #endif | ||
| 5114 | s++; | ||
| 5115 | } | ||
| 5116 | 5133 | ||
| 5117 | err = ReceiveNextEvent (0, NULL, timeout_sec, kEventLeaveInQueue, NULL); | 5134 | for (fd = minfd; fd < nfds; fd++) |
| 5135 | if (FD_ISSET (fd, rfds) || (wfds && FD_ISSET (fd, wfds))) | ||
| 5136 | { | ||
| 5137 | void *key = (void *) fd; | ||
| 5138 | CFRunLoopSourceRef source = | ||
| 5139 | (CFRunLoopSourceRef) CFDictionaryGetValue (sources, key); | ||
| 5140 | |||
| 5141 | if (source == NULL) | ||
| 5142 | { | ||
| 5143 | CFSocketRef socket = | ||
| 5144 | CFSocketCreateWithNative (NULL, fd, | ||
| 5145 | (kCFSocketReadCallBack | ||
| 5146 | | kCFSocketConnectCallBack), | ||
| 5147 | socket_callback, &context); | ||
| 5148 | |||
| 5149 | if (socket == NULL) | ||
| 5150 | continue; | ||
| 5151 | source = CFSocketCreateRunLoopSource (NULL, socket, 0); | ||
| 5152 | CFRelease (socket); | ||
| 5153 | if (source == NULL) | ||
| 5154 | continue; | ||
| 5155 | CFDictionaryAddValue (sources, key, source); | ||
| 5156 | CFRelease (source); | ||
| 5157 | } | ||
| 5158 | CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode); | ||
| 5159 | } | ||
| 5118 | 5160 | ||
| 5119 | do | 5161 | #if USE_CG_DRAWING |
| 5120 | { | 5162 | mac_prepare_for_quickdraw (NULL); |
| 5121 | --s; | ||
| 5122 | #ifdef SELECT_INVALIDATE_CFSOCKET | ||
| 5123 | CFSocketInvalidate (*s); | ||
| 5124 | #else | ||
| 5125 | CFRunLoopRemoveSource (runloop, *s, kCFRunLoopDefaultMode); | ||
| 5126 | #endif | 5163 | #endif |
| 5127 | CFRelease (*s); | 5164 | err = ReceiveNextEvent (0, NULL, timeoutval, |
| 5128 | } | 5165 | kEventLeaveInQueue, NULL); |
| 5129 | while (s != shead); | ||
| 5130 | |||
| 5131 | xfree (shead); | ||
| 5132 | 5166 | ||
| 5133 | if (err) | 5167 | for (fd = minfd; fd < nfds; fd++) |
| 5134 | { | 5168 | if (FD_ISSET (fd, rfds) || (wfds && FD_ISSET (fd, wfds))) |
| 5135 | FD_ZERO (rfds); | 5169 | { |
| 5136 | r = 0; | 5170 | void *key = (void *) fd; |
| 5137 | } | 5171 | CFRunLoopSourceRef source = |
| 5138 | else | 5172 | (CFRunLoopSourceRef) CFDictionaryGetValue (sources, key); |
| 5139 | { | ||
| 5140 | FlushEventsMatchingListFromQueue (GetCurrentEventQueue (), | ||
| 5141 | GetEventTypeCount (specs), | ||
| 5142 | specs); | ||
| 5143 | EMACS_SET_SECS_USECS (select_timeout, 0, 0); | ||
| 5144 | r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout); | ||
| 5145 | } | ||
| 5146 | 5173 | ||
| 5147 | UNBLOCK_INPUT; | 5174 | CFRunLoopRemoveSource (runloop, source, kCFRunLoopDefaultMode); |
| 5175 | } | ||
| 5176 | } | ||
| 5177 | UNBLOCK_INPUT; | ||
| 5148 | 5178 | ||
| 5149 | return r; | 5179 | if (err == noErr || err == eventLoopQuitErr) |
| 5150 | } | 5180 | { |
| 5181 | EMACS_SET_SECS_USECS (select_timeout, 0, 0); | ||
| 5182 | return select_and_poll_event (nfds, rfds, wfds, efds, | ||
| 5183 | &select_timeout); | ||
| 5184 | } | ||
| 5185 | else | ||
| 5186 | { | ||
| 5187 | FD_ZERO (rfds); | ||
| 5188 | if (wfds) | ||
| 5189 | FD_ZERO (wfds); | ||
| 5190 | return 0; | ||
| 5191 | } | ||
| 5151 | #endif /* SELECT_USE_CFSOCKET */ | 5192 | #endif /* SELECT_USE_CFSOCKET */ |
| 5152 | } | 5193 | } |
| 5153 | 5194 | ||
| 5154 | poll_periodically: | 5195 | poll_periodically: |
| 5155 | { | 5196 | { |
| 5156 | EMACS_TIME end_time, now, remaining_time; | 5197 | EMACS_TIME end_time, now, remaining_time; |
| 5157 | SELECT_TYPE orfds = *rfds, owfds, oefds; | ||
| 5158 | 5198 | ||
| 5159 | if (wfds) | ||
| 5160 | owfds = *wfds; | ||
| 5161 | if (efds) | ||
| 5162 | oefds = *efds; | ||
| 5163 | if (timeout) | 5199 | if (timeout) |
| 5164 | { | 5200 | { |
| 5165 | remaining_time = *timeout; | 5201 | remaining_time = *timeout; |
| @@ -5172,15 +5208,15 @@ sys_select (n, rfds, wfds, efds, timeout) | |||
| 5172 | EMACS_SET_SECS_USECS (select_timeout, 0, SELECT_POLLING_PERIOD_USEC); | 5208 | EMACS_SET_SECS_USECS (select_timeout, 0, SELECT_POLLING_PERIOD_USEC); |
| 5173 | if (timeout && EMACS_TIME_LT (remaining_time, select_timeout)) | 5209 | if (timeout && EMACS_TIME_LT (remaining_time, select_timeout)) |
| 5174 | select_timeout = remaining_time; | 5210 | select_timeout = remaining_time; |
| 5175 | r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout); | 5211 | r = select_and_poll_event (nfds, rfds, wfds, efds, &select_timeout); |
| 5176 | if (r != 0) | 5212 | if (r != 0) |
| 5177 | return r; | 5213 | return r; |
| 5178 | 5214 | ||
| 5179 | *rfds = orfds; | 5215 | *rfds = ofds[0]; |
| 5180 | if (wfds) | 5216 | if (wfds) |
| 5181 | *wfds = owfds; | 5217 | *wfds = ofds[1]; |
| 5182 | if (efds) | 5218 | if (efds) |
| 5183 | *efds = oefds; | 5219 | *efds = ofds[2]; |
| 5184 | 5220 | ||
| 5185 | if (timeout) | 5221 | if (timeout) |
| 5186 | { | 5222 | { |
| @@ -5190,12 +5226,8 @@ sys_select (n, rfds, wfds, efds, timeout) | |||
| 5190 | } | 5226 | } |
| 5191 | while (!timeout || EMACS_TIME_LT (now, end_time)); | 5227 | while (!timeout || EMACS_TIME_LT (now, end_time)); |
| 5192 | 5228 | ||
| 5193 | FD_ZERO (rfds); | 5229 | EMACS_SET_SECS_USECS (select_timeout, 0, 0); |
| 5194 | if (wfds) | 5230 | return select_and_poll_event (nfds, rfds, wfds, efds, &select_timeout); |
| 5195 | FD_ZERO (wfds); | ||
| 5196 | if (efds) | ||
| 5197 | FD_ZERO (efds); | ||
| 5198 | return 0; | ||
| 5199 | } | 5231 | } |
| 5200 | } | 5232 | } |
| 5201 | 5233 | ||
| @@ -5387,6 +5419,7 @@ syms_of_mac () | |||
| 5387 | #if TARGET_API_MAC_CARBON | 5419 | #if TARGET_API_MAC_CARBON |
| 5388 | defsubr (&Smac_get_preference); | 5420 | defsubr (&Smac_get_preference); |
| 5389 | defsubr (&Smac_code_convert_string); | 5421 | defsubr (&Smac_code_convert_string); |
| 5422 | defsubr (&Smac_process_hi_command); | ||
| 5390 | #endif | 5423 | #endif |
| 5391 | 5424 | ||
| 5392 | defsubr (&Smac_set_file_creator); | 5425 | defsubr (&Smac_set_file_creator); |