diff options
| author | YAMAMOTO Mitsuharu | 2006-09-08 08:17:58 +0000 |
|---|---|---|
| committer | YAMAMOTO Mitsuharu | 2006-09-08 08:17:58 +0000 |
| commit | 3e51e9ac8ea02708ce46926e1d23af9f528e42dd (patch) | |
| tree | db98533ede42286d0d2e74a944ec9122f3af6cb1 /src/mac.c | |
| parent | dbcdba77e6d0b3ce23ceeba55ac6a1b3e25e3898 (diff) | |
| download | emacs-3e51e9ac8ea02708ce46926e1d23af9f528e42dd.tar.gz emacs-3e51e9ac8ea02708ce46926e1d23af9f528e42dd.zip | |
[!MAC_OSX] Don't include keyboard.h.
[!MAC_OSX] (select): Try detect_input_pending before ReceiveNextEvent
in the same BLOCK_INPUT block, in case that some input has already
been read asynchronously. Pretend to be interrupted by a signal
if some input is available.
[MAC_OSX] (select_and_poll_event, sys_select): Likewise.
(SELECT_POLLING_PERIOD_USEC) [SELECT_USE_CFSOCKET]: Change to 100000.
Now used for ReceiveNextEvent timeout instead of select timeout.
(EVENT_CLASS_SOCK) [SELECT_USE_CFSOCKET]: Remove macro.
[SELECT_USE_CFSOCKET] (socket_callback): Add non-blocking connect
support. Quit event loop.
[MAC_OSX] (sys_select) [SELECT_USE_CFSOCKET]: Add non-blocking
connect support. Reuse previously allocated CFRunLoopSource.
(Fmac_process_hi_command) [TARGET_API_MAC_CARBON]: New function.
(syms_of_mac) [TARGET_API_MAC_CARBON]: Defsubr it.
Diffstat (limited to 'src/mac.c')
| -rw-r--r-- | src/mac.c | 454 |
1 files changed, 240 insertions, 214 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 (n, 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,22 @@ 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 | #define SELECT_POLLING_PERIOD_USEC 100000 |
| 4961 | #ifdef SELECT_USE_CFSOCKET | 4979 | #if SELECT_USE_CFSOCKET |
| 4962 | #define SELECT_TIMEOUT_THRESHOLD_RUNLOOP 0.2 | 4980 | #define SELECT_TIMEOUT_THRESHOLD_RUNLOOP 0.2 |
| 4963 | #define EVENT_CLASS_SOCK 'Sock' | ||
| 4964 | 4981 | ||
| 4965 | static void | 4982 | static void |
| 4966 | socket_callback (s, type, address, data, info) | 4983 | socket_callback (s, type, address, data, info) |
| @@ -4970,196 +4987,208 @@ socket_callback (s, type, address, data, info) | |||
| 4970 | const void *data; | 4987 | const void *data; |
| 4971 | void *info; | 4988 | void *info; |
| 4972 | { | 4989 | { |
| 4973 | EventRef event; | 4990 | int fd = CFSocketGetNative (s); |
| 4991 | SELECT_TYPE *ofds = (SELECT_TYPE *)info; | ||
| 4974 | 4992 | ||
| 4975 | CreateEvent (NULL, EVENT_CLASS_SOCK, 0, 0, kEventAttributeNone, &event); | 4993 | if ((type == kCFSocketReadCallBack && FD_ISSET (fd, &ofds[0])) |
| 4976 | PostEventToQueue (GetCurrentEventQueue (), event, kEventPriorityStandard); | 4994 | || (type == kCFSocketConnectCallBack && FD_ISSET (fd, &ofds[1]))) |
| 4977 | ReleaseEvent (event); | 4995 | QuitEventLoop (GetCurrentEventLoop ()); |
| 4978 | } | 4996 | } |
| 4979 | #endif /* SELECT_USE_CFSOCKET */ | 4997 | #endif /* SELECT_USE_CFSOCKET */ |
| 4980 | 4998 | ||
| 4981 | static int | 4999 | static int |
| 4982 | select_and_poll_event (n, rfds, wfds, efds, timeout) | 5000 | select_and_poll_event (nfds, rfds, wfds, efds, timeout) |
| 4983 | int n; | 5001 | int nfds; |
| 4984 | SELECT_TYPE *rfds; | 5002 | SELECT_TYPE *rfds, *wfds, *efds; |
| 4985 | SELECT_TYPE *wfds; | 5003 | EMACS_TIME *timeout; |
| 4986 | SELECT_TYPE *efds; | ||
| 4987 | struct timeval *timeout; | ||
| 4988 | { | 5004 | { |
| 4989 | int r; | 5005 | OSStatus err = noErr; |
| 4990 | OSStatus err; | 5006 | int r = 0; |
| 4991 | 5007 | ||
| 4992 | r = select (n, rfds, wfds, efds, timeout); | 5008 | /* Try detect_input_pending before ReceiveNextEvent in the same |
| 4993 | if (r != -1) | 5009 | BLOCK_INPUT block, in case that some input has already been read |
| 5010 | asynchronously. */ | ||
| 5011 | BLOCK_INPUT; | ||
| 5012 | if (!detect_input_pending ()) | ||
| 4994 | { | 5013 | { |
| 4995 | BLOCK_INPUT; | 5014 | EMACS_TIME select_timeout; |
| 4996 | err = ReceiveNextEvent (0, NULL, kEventDurationNoWait, | 5015 | EventTimeout timeoutval = |
| 4997 | kEventLeaveInQueue, NULL); | 5016 | (timeout |
| 4998 | UNBLOCK_INPUT; | 5017 | ? (EMACS_SECS (*timeout) * kEventDurationSecond |
| 4999 | if (err == noErr) | 5018 | + EMACS_USECS (*timeout) * kEventDurationMicrosecond) |
| 5019 | : kEventDurationForever); | ||
| 5020 | |||
| 5021 | EMACS_SET_SECS_USECS (select_timeout, 0, 0); | ||
| 5022 | r = select (nfds, rfds, wfds, efds, &select_timeout); | ||
| 5023 | if (timeoutval == 0.0) | ||
| 5024 | err = eventLoopTimedOutErr; | ||
| 5025 | else if (r == 0) | ||
| 5000 | { | 5026 | { |
| 5001 | FD_SET (0, rfds); | 5027 | #if USE_CG_DRAWING |
| 5002 | r++; | 5028 | mac_prepare_for_quickdraw (NULL); |
| 5029 | #endif | ||
| 5030 | err = ReceiveNextEvent (0, NULL, timeoutval, | ||
| 5031 | kEventLeaveInQueue, NULL); | ||
| 5003 | } | 5032 | } |
| 5004 | } | 5033 | } |
| 5005 | return r; | 5034 | UNBLOCK_INPUT; |
| 5006 | } | ||
| 5007 | 5035 | ||
| 5008 | #if MAC_OS_X_VERSION_MAX_ALLOWED < 1020 | 5036 | if (r != 0) |
| 5009 | #undef SELECT_INVALIDATE_CFSOCKET | 5037 | return r; |
| 5010 | #endif | 5038 | else if (err == noErr) |
| 5039 | { | ||
| 5040 | /* Pretend that `select' is interrupted by a signal. */ | ||
| 5041 | detect_input_pending (); | ||
| 5042 | errno = EINTR; | ||
| 5043 | return -1; | ||
| 5044 | } | ||
| 5045 | else | ||
| 5046 | return 0; | ||
| 5047 | } | ||
| 5011 | 5048 | ||
| 5012 | int | 5049 | int |
| 5013 | sys_select (n, rfds, wfds, efds, timeout) | 5050 | sys_select (nfds, rfds, wfds, efds, timeout) |
| 5014 | int n; | 5051 | int nfds; |
| 5015 | SELECT_TYPE *rfds; | 5052 | SELECT_TYPE *rfds, *wfds, *efds; |
| 5016 | SELECT_TYPE *wfds; | 5053 | EMACS_TIME *timeout; |
| 5017 | SELECT_TYPE *efds; | ||
| 5018 | struct timeval *timeout; | ||
| 5019 | { | 5054 | { |
| 5020 | OSStatus err; | 5055 | OSStatus err = noErr; |
| 5021 | int i, r; | 5056 | int r; |
| 5022 | EMACS_TIME select_timeout; | 5057 | EMACS_TIME select_timeout; |
| 5058 | SELECT_TYPE ofds[3]; | ||
| 5023 | 5059 | ||
| 5024 | if (inhibit_window_system || noninteractive | 5060 | if (inhibit_window_system || noninteractive |
| 5025 | || rfds == NULL || !FD_ISSET (0, rfds)) | 5061 | || rfds == NULL || !FD_ISSET (0, rfds)) |
| 5026 | return select (n, rfds, wfds, efds, timeout); | 5062 | return select (nfds, rfds, wfds, efds, timeout); |
| 5027 | 5063 | ||
| 5028 | FD_CLR (0, rfds); | 5064 | FD_CLR (0, rfds); |
| 5065 | ofds[0] = *rfds; | ||
| 5029 | 5066 | ||
| 5030 | if (wfds == NULL && efds == NULL) | 5067 | if (wfds) |
| 5031 | { | 5068 | ofds[1] = *wfds; |
| 5032 | int nsocks = 0; | 5069 | else |
| 5033 | SELECT_TYPE orfds = *rfds; | 5070 | FD_ZERO (&ofds[1]); |
| 5034 | 5071 | ||
| 5035 | EventTimeout timeout_sec = | 5072 | if (efds) |
| 5073 | ofds[2] = *efds; | ||
| 5074 | else | ||
| 5075 | { | ||
| 5076 | int maxfd; | ||
| 5077 | EventTimeout timeoutval = | ||
| 5036 | (timeout | 5078 | (timeout |
| 5037 | ? (EMACS_SECS (*timeout) * kEventDurationSecond | 5079 | ? (EMACS_SECS (*timeout) * kEventDurationSecond |
| 5038 | + EMACS_USECS (*timeout) * kEventDurationMicrosecond) | 5080 | + EMACS_USECS (*timeout) * kEventDurationMicrosecond) |
| 5039 | : kEventDurationForever); | 5081 | : kEventDurationForever); |
| 5040 | 5082 | ||
| 5041 | for (i = 1; i < n; i++) | 5083 | for (maxfd = nfds - 1; maxfd > 0; maxfd--) |
| 5042 | if (FD_ISSET (i, rfds)) | 5084 | if (FD_ISSET (maxfd, rfds) || (wfds && FD_ISSET (maxfd, wfds))) |
| 5043 | nsocks++; | 5085 | break; |
| 5044 | 5086 | ||
| 5045 | if (nsocks == 0) | 5087 | if (maxfd == 0) |
| 5046 | { | 5088 | return select_and_poll_event (nfds, rfds, wfds, efds, timeout); |
| 5047 | BLOCK_INPUT; | ||
| 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 | } | ||
| 5059 | 5089 | ||
| 5060 | #if USE_CG_DRAWING | ||
| 5061 | mac_prepare_for_quickdraw (NULL); | ||
| 5062 | #endif | ||
| 5063 | /* Avoid initial overhead of RunLoop setup for the case that | 5090 | /* Avoid initial overhead of RunLoop setup for the case that |
| 5064 | some input is already available. */ | 5091 | some input is already available. */ |
| 5065 | EMACS_SET_SECS_USECS (select_timeout, 0, 0); | 5092 | EMACS_SET_SECS_USECS (select_timeout, 0, 0); |
| 5066 | r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout); | 5093 | r = select_and_poll_event (nfds, rfds, wfds, efds, &select_timeout); |
| 5067 | if (r != 0 || timeout_sec == 0.0) | 5094 | if (r != 0 || timeoutval == 0.0) |
| 5068 | return r; | 5095 | return r; |
| 5069 | 5096 | ||
| 5070 | *rfds = orfds; | 5097 | *rfds = ofds[0]; |
| 5098 | if (wfds) | ||
| 5099 | *wfds = ofds[1]; | ||
| 5071 | 5100 | ||
| 5072 | #ifdef SELECT_USE_CFSOCKET | 5101 | #if SELECT_USE_CFSOCKET |
| 5073 | if (timeout_sec > 0 && timeout_sec <= SELECT_TIMEOUT_THRESHOLD_RUNLOOP) | 5102 | if (timeoutval > 0 && timeoutval <= SELECT_TIMEOUT_THRESHOLD_RUNLOOP) |
| 5074 | goto poll_periodically; | 5103 | goto poll_periodically; |
| 5075 | 5104 | ||
| 5076 | { | 5105 | /* Try detect_input_pending before ReceiveNextEvent in the same |
| 5077 | CFRunLoopRef runloop = | 5106 | BLOCK_INPUT block, in case that some input has already been |
| 5078 | (CFRunLoopRef) GetCFRunLoopFromEventLoop (GetCurrentEventLoop ()); | 5107 | read asynchronously. */ |
| 5079 | EventTypeSpec specs[] = {{EVENT_CLASS_SOCK, 0}}; | 5108 | BLOCK_INPUT; |
| 5080 | #ifdef SELECT_INVALIDATE_CFSOCKET | 5109 | if (!detect_input_pending ()) |
| 5081 | CFSocketRef *shead, *s; | 5110 | { |
| 5082 | #else | 5111 | int minfd, fd; |
| 5083 | CFRunLoopSourceRef *shead, *s; | 5112 | CFRunLoopRef runloop = |
| 5084 | #endif | 5113 | (CFRunLoopRef) GetCFRunLoopFromEventLoop (GetCurrentEventLoop ()); |
| 5085 | 5114 | static CFSocketContext context; | |
| 5086 | BLOCK_INPUT; | 5115 | static CFMutableDictionaryRef sources; |
| 5087 | 5116 | ||
| 5088 | #ifdef SELECT_INVALIDATE_CFSOCKET | 5117 | context.info = ofds; |
| 5089 | shead = xmalloc (sizeof (CFSocketRef) * nsocks); | 5118 | if (sources == NULL) |
| 5090 | #else | 5119 | sources = |
| 5091 | shead = xmalloc (sizeof (CFRunLoopSourceRef) * nsocks); | 5120 | CFDictionaryCreateMutable (NULL, 0, NULL, |
| 5092 | #endif | 5121 | &kCFTypeDictionaryValueCallBacks); |
| 5093 | s = shead; | 5122 | |
| 5094 | for (i = 1; i < n; i++) | 5123 | for (minfd = 1; minfd < maxfd; minfd++) |
| 5095 | if (FD_ISSET (i, rfds)) | 5124 | if (FD_ISSET (minfd, rfds) || (wfds && FD_ISSET (minfd, wfds))) |
| 5096 | { | 5125 | break; |
| 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 | 5126 | ||
| 5117 | err = ReceiveNextEvent (0, NULL, timeout_sec, kEventLeaveInQueue, NULL); | 5127 | for (fd = minfd; fd <= maxfd; fd++) |
| 5128 | if (FD_ISSET (fd, rfds) || (wfds && FD_ISSET (fd, wfds))) | ||
| 5129 | { | ||
| 5130 | void *key = (void *) fd; | ||
| 5131 | CFRunLoopSourceRef source = | ||
| 5132 | (CFRunLoopSourceRef) CFDictionaryGetValue (sources, key); | ||
| 5133 | |||
| 5134 | if (source == NULL) | ||
| 5135 | { | ||
| 5136 | CFSocketRef socket = | ||
| 5137 | CFSocketCreateWithNative (NULL, fd, | ||
| 5138 | (kCFSocketReadCallBack | ||
| 5139 | | kCFSocketConnectCallBack), | ||
| 5140 | socket_callback, &context); | ||
| 5141 | |||
| 5142 | if (socket == NULL) | ||
| 5143 | continue; | ||
| 5144 | source = CFSocketCreateRunLoopSource (NULL, socket, 0); | ||
| 5145 | CFRelease (socket); | ||
| 5146 | if (source == NULL) | ||
| 5147 | continue; | ||
| 5148 | CFDictionaryAddValue (sources, key, source); | ||
| 5149 | CFRelease (source); | ||
| 5150 | } | ||
| 5151 | CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode); | ||
| 5152 | } | ||
| 5118 | 5153 | ||
| 5119 | do | 5154 | #if USE_CG_DRAWING |
| 5120 | { | 5155 | mac_prepare_for_quickdraw (NULL); |
| 5121 | --s; | ||
| 5122 | #ifdef SELECT_INVALIDATE_CFSOCKET | ||
| 5123 | CFSocketInvalidate (*s); | ||
| 5124 | #else | ||
| 5125 | CFRunLoopRemoveSource (runloop, *s, kCFRunLoopDefaultMode); | ||
| 5126 | #endif | 5156 | #endif |
| 5127 | CFRelease (*s); | 5157 | err = ReceiveNextEvent (0, NULL, timeoutval, |
| 5128 | } | 5158 | kEventLeaveInQueue, NULL); |
| 5129 | while (s != shead); | ||
| 5130 | |||
| 5131 | xfree (shead); | ||
| 5132 | 5159 | ||
| 5133 | if (err) | 5160 | for (fd = minfd; fd <= maxfd; fd++) |
| 5134 | { | 5161 | if (FD_ISSET (fd, rfds) || (wfds && FD_ISSET (fd, wfds))) |
| 5135 | FD_ZERO (rfds); | 5162 | { |
| 5136 | r = 0; | 5163 | void *key = (void *) fd; |
| 5137 | } | 5164 | CFRunLoopSourceRef source = |
| 5138 | else | 5165 | (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 | 5166 | ||
| 5147 | UNBLOCK_INPUT; | 5167 | CFRunLoopRemoveSource (runloop, source, kCFRunLoopDefaultMode); |
| 5168 | } | ||
| 5169 | } | ||
| 5170 | UNBLOCK_INPUT; | ||
| 5148 | 5171 | ||
| 5149 | return r; | 5172 | if (err == noErr || err == eventLoopQuitErr) |
| 5150 | } | 5173 | { |
| 5174 | EMACS_SET_SECS_USECS (select_timeout, 0, 0); | ||
| 5175 | return select_and_poll_event (nfds, rfds, wfds, efds, | ||
| 5176 | &select_timeout); | ||
| 5177 | } | ||
| 5178 | else | ||
| 5179 | { | ||
| 5180 | FD_ZERO (rfds); | ||
| 5181 | if (wfds) | ||
| 5182 | FD_ZERO (wfds); | ||
| 5183 | return 0; | ||
| 5184 | } | ||
| 5151 | #endif /* SELECT_USE_CFSOCKET */ | 5185 | #endif /* SELECT_USE_CFSOCKET */ |
| 5152 | } | 5186 | } |
| 5153 | 5187 | ||
| 5154 | poll_periodically: | 5188 | poll_periodically: |
| 5155 | { | 5189 | { |
| 5156 | EMACS_TIME end_time, now, remaining_time; | 5190 | EMACS_TIME end_time, now, remaining_time; |
| 5157 | SELECT_TYPE orfds = *rfds, owfds, oefds; | ||
| 5158 | 5191 | ||
| 5159 | if (wfds) | ||
| 5160 | owfds = *wfds; | ||
| 5161 | if (efds) | ||
| 5162 | oefds = *efds; | ||
| 5163 | if (timeout) | 5192 | if (timeout) |
| 5164 | { | 5193 | { |
| 5165 | remaining_time = *timeout; | 5194 | remaining_time = *timeout; |
| @@ -5172,15 +5201,15 @@ sys_select (n, rfds, wfds, efds, timeout) | |||
| 5172 | EMACS_SET_SECS_USECS (select_timeout, 0, SELECT_POLLING_PERIOD_USEC); | 5201 | EMACS_SET_SECS_USECS (select_timeout, 0, SELECT_POLLING_PERIOD_USEC); |
| 5173 | if (timeout && EMACS_TIME_LT (remaining_time, select_timeout)) | 5202 | if (timeout && EMACS_TIME_LT (remaining_time, select_timeout)) |
| 5174 | select_timeout = remaining_time; | 5203 | select_timeout = remaining_time; |
| 5175 | r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout); | 5204 | r = select_and_poll_event (nfds, rfds, wfds, efds, &select_timeout); |
| 5176 | if (r != 0) | 5205 | if (r != 0) |
| 5177 | return r; | 5206 | return r; |
| 5178 | 5207 | ||
| 5179 | *rfds = orfds; | 5208 | *rfds = ofds[0]; |
| 5180 | if (wfds) | 5209 | if (wfds) |
| 5181 | *wfds = owfds; | 5210 | *wfds = ofds[1]; |
| 5182 | if (efds) | 5211 | if (efds) |
| 5183 | *efds = oefds; | 5212 | *efds = ofds[2]; |
| 5184 | 5213 | ||
| 5185 | if (timeout) | 5214 | if (timeout) |
| 5186 | { | 5215 | { |
| @@ -5190,12 +5219,8 @@ sys_select (n, rfds, wfds, efds, timeout) | |||
| 5190 | } | 5219 | } |
| 5191 | while (!timeout || EMACS_TIME_LT (now, end_time)); | 5220 | while (!timeout || EMACS_TIME_LT (now, end_time)); |
| 5192 | 5221 | ||
| 5193 | FD_ZERO (rfds); | 5222 | EMACS_SET_SECS_USECS (select_timeout, 0, 0); |
| 5194 | if (wfds) | 5223 | 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 | } | 5224 | } |
| 5200 | } | 5225 | } |
| 5201 | 5226 | ||
| @@ -5387,6 +5412,7 @@ syms_of_mac () | |||
| 5387 | #if TARGET_API_MAC_CARBON | 5412 | #if TARGET_API_MAC_CARBON |
| 5388 | defsubr (&Smac_get_preference); | 5413 | defsubr (&Smac_get_preference); |
| 5389 | defsubr (&Smac_code_convert_string); | 5414 | defsubr (&Smac_code_convert_string); |
| 5415 | defsubr (&Smac_process_hi_command); | ||
| 5390 | #endif | 5416 | #endif |
| 5391 | 5417 | ||
| 5392 | defsubr (&Smac_set_file_creator); | 5418 | defsubr (&Smac_set_file_creator); |