/[emacs]/emacs/src/mac.c
ViewVC logotype

Diff of /emacs/src/mac.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.24 by tamm, Fri Dec 3 17:00:11 2004 UTC revision 1.25 by tamm, Mon Dec 27 17:27:30 2004 UTC
# Line 845  check_alarm () Line 845  check_alarm ()
845  }  }
846    
847    
848    extern Boolean mac_wait_next_event (EventRecord *, UInt32, Boolean);
849    
850  int  int
851  select (n,  rfds, wfds, efds, timeout)  select (n,  rfds, wfds, efds, timeout)
852    int n;    int n;
# Line 853  select (n,  rfds, wfds, efds, timeout) Line 855  select (n,  rfds, wfds, efds, timeout)
855    SELECT_TYPE *efds;    SELECT_TYPE *efds;
856    struct timeval *timeout;    struct timeval *timeout;
857  {  {
858  #ifdef TARGET_API_MAC_CARBON  #if TARGET_API_MAC_CARBON
859    return 1;    return 1;
860  #else /* not TARGET_API_MAC_CARBON */  #else /* not TARGET_API_MAC_CARBON */
   EMACS_TIME end_time, now;  
861    EventRecord e;    EventRecord e;
862      UInt32 sleep_time = EMACS_SECS (*timeout) * 60 +
863        ((EMACS_USECS (*timeout) * 60) / 1000000);
864    
865    /* Can only handle wait for keyboard input.  */    /* Can only handle wait for keyboard input.  */
866    if (n > 1 || wfds || efds)    if (n > 1 || wfds || efds)
867      return -1;      return -1;
868    
869    EMACS_GET_TIME (end_time);    /* Also return true if an event other than a keyDown has occurred.
870    EMACS_ADD_TIME (end_time, end_time, *timeout);       This causes kbd_buffer_get_event in keyboard.c to call
871         read_avail_input which in turn calls XTread_socket to poll for
872    do       these events.  Otherwise these never get processed except but a
873      {       very slow poll timer.  */
874        /* Also return true if an event other than a keyDown has    if (FD_ISSET (0, rfds) && mac_wait_next_event (&e, sleep_time, false))
875           occurred.  This causes kbd_buffer_get_event in keyboard.c to      return 1;
          call read_avail_input which in turn calls XTread_socket to  
          poll for these events.  Otherwise these never get processed  
          except but a very slow poll timer.  */  
       if (FD_ISSET (0, rfds) && EventAvail (everyEvent, &e))  
         return 1;  
   
       /* Also check movement of the mouse.  */  
       {  
         Point mouse_pos;  
         static Point old_mouse_pos = {-1, -1};  
   
         GetMouse (&mouse_pos);  
         if (!EqualPt (mouse_pos, old_mouse_pos))  
           {  
             old_mouse_pos = mouse_pos;  
             return 1;  
           }  
       }  
   
       WaitNextEvent (0, &e, 1UL, NULL); /* Accept no event; wait 1  
                                            tic. by T.I. */  
   
       EMACS_GET_TIME (now);  
       EMACS_SUB_TIME (now, end_time, now);  
     }  
   while (!EMACS_TIME_NEG_P (now));  
876    
877    return 0;    return 0;
878  #endif /* not TARGET_API_MAC_CARBON */  #endif /* not TARGET_API_MAC_CARBON */
# Line 1996  run_mac_command (argv, workdir, infn, ou Line 1973  run_mac_command (argv, workdir, infn, ou
1973       const char *workdir;       const char *workdir;
1974       const char *infn, *outfn, *errfn;       const char *infn, *outfn, *errfn;
1975  {  {
1976  #ifdef TARGET_API_MAC_CARBON  #if TARGET_API_MAC_CARBON
1977    return -1;    return -1;
1978  #else /* not TARGET_API_MAC_CARBON */  #else /* not TARGET_API_MAC_CARBON */
1979    char macappname[MAXPATHLEN+1], macworkdir[MAXPATHLEN+1];    char macappname[MAXPATHLEN+1], macworkdir[MAXPATHLEN+1];
# Line 2081  run_mac_command (argv, workdir, infn, ou Line 2058  run_mac_command (argv, workdir, infn, ou
2058            strcat (t, newargv[0]);            strcat (t, newargv[0]);
2059  #endif /* 0 */  #endif /* 0 */
2060            Lisp_Object path;            Lisp_Object path;
2061            openp (Vexec_path, build_string (newargv[0]), EXEC_SUFFIXES, &path,            openp (Vexec_path, build_string (newargv[0]), Vexec_suffixes, &path,
2062                   make_number (X_OK));                   make_number (X_OK));
2063    
2064            if (NILP (path))            if (NILP (path))
# Line 2793  and t is the same as `SECONDARY'.  */) Line 2770  and t is the same as `SECONDARY'.  */)
2770    return Qnil;    return Qnil;
2771  }  }
2772    
2773    extern void mac_clear_font_name_table P_ ((void));
2774    
2775    DEFUN ("mac-clear-font-name-table", Fmac_clear_font_name_table, Smac_clear_font_name_table, 0, 0, 0,
2776           doc: /* Clear the font name table.  */)
2777      ()
2778    {
2779      check_mac ();
2780      mac_clear_font_name_table ();
2781      return Qnil;
2782    }
2783    
2784  #ifdef MAC_OSX  #ifdef MAC_OSX
2785  #undef select  #undef select
2786    
2787  extern int inhibit_window_system;  extern int inhibit_window_system;
2788  extern int noninteractive;  extern int noninteractive;
2789    
2790  /* When Emacs is started from the Finder, SELECT always immediately  /* Unlike in X11, window events in Carbon do not come from sockets.
2791     returns as if input is present when file descriptor 0 is polled for     So we cannot simply use `select' to monitor two kinds of inputs:
2792     input.  Strangely, when Emacs is run as a GUI application from the     window events and process outputs.  We emulate such functionality
2793     command line, it blocks in the same situation.  This `wrapper' of     by regarding fd 0 as the window event channel and simultaneously
2794     the system call SELECT corrects this discrepancy.  */     monitoring both kinds of input channels.  It is implemented by
2795       dividing into some cases:
2796       1. The window event channel is not involved.
2797          -> Use `select'.
2798       2. Sockets are not involved.
2799          -> Use ReceiveNextEvent.
2800       3. [If SELECT_USE_CFSOCKET is defined]
2801          Only the window event channel and socket read channels are
2802          involved, and timeout is not too short (greater than
2803          SELECT_TIMEOUT_THRESHHOLD_RUNLOOP seconds).
2804          -> Create CFSocket for each socket and add it into the current
2805             event RunLoop so that an `ready-to-read' event can be posted
2806             to the event queue that is also used for window events.  Then
2807             ReceiveNextEvent can wait for both kinds of inputs.
2808       4. Otherwise.
2809          -> Periodically poll the window input channel while repeatedly
2810             executing `select' with a short timeout
2811             (SELECT_POLLING_PERIOD_USEC microseconds).  */
2812    
2813    #define SELECT_POLLING_PERIOD_USEC 20000
2814    #ifdef SELECT_USE_CFSOCKET
2815    #define SELECT_TIMEOUT_THRESHOLD_RUNLOOP 0.2
2816    #define EVENT_CLASS_SOCK 'Sock'
2817    
2818    static void
2819    socket_callback (s, type, address, data, info)
2820         CFSocketRef s;
2821         CFSocketCallBackType type;
2822         CFDataRef address;
2823         const void *data;
2824         void *info;
2825    {
2826      EventRef event;
2827    
2828      CreateEvent (NULL, EVENT_CLASS_SOCK, 0, 0, kEventAttributeNone, &event);
2829      PostEventToQueue (GetCurrentEventQueue (), event, kEventPriorityStandard);
2830      ReleaseEvent (event);
2831    }
2832    #endif  /* SELECT_USE_CFSOCKET */
2833    
2834    static int
2835    select_and_poll_event (n, rfds, wfds, efds, timeout)
2836         int n;
2837         SELECT_TYPE *rfds;
2838         SELECT_TYPE *wfds;
2839         SELECT_TYPE *efds;
2840         struct timeval *timeout;
2841    {
2842      int r;
2843      OSErr err;
2844    
2845      r = select (n, rfds, wfds, efds, timeout);
2846      if (r != -1)
2847        {
2848          BLOCK_INPUT;
2849          err = ReceiveNextEvent (0, NULL, kEventDurationNoWait,
2850                                  kEventLeaveInQueue, NULL);
2851          UNBLOCK_INPUT;
2852          if (err == noErr)
2853            {
2854              FD_SET (0, rfds);
2855              r++;
2856            }
2857        }
2858      return r;
2859    }
2860    
2861    #ifndef MAC_OS_X_VERSION_10_2
2862    #undef SELECT_INVALIDATE_CFSOCKET
2863    #endif
2864    
2865  int  int
2866  sys_select (n, rfds, wfds, efds, timeout)  sys_select (n, rfds, wfds, efds, timeout)
2867       int n;       int n;
# Line 2813  sys_select (n, rfds, wfds, efds, timeout Line 2871  sys_select (n, rfds, wfds, efds, timeout
2871       struct timeval *timeout;       struct timeval *timeout;
2872  {  {
2873    OSErr err;    OSErr err;
2874    EMACS_TIME end_time, now, remaining_time;    int i, r;
2875      EMACS_TIME select_timeout;
2876    
2877    if (inhibit_window_system || noninteractive    if (inhibit_window_system || noninteractive
2878        || rfds == NULL || !FD_ISSET (0, rfds))        || rfds == NULL || !FD_ISSET (0, rfds))
2879      return select (n, rfds, wfds, efds, timeout);      return select (n, rfds, wfds, efds, timeout);
2880      
2881      FD_CLR (0, rfds);
2882    
2883    if (wfds == NULL && efds == NULL)    if (wfds == NULL && efds == NULL)
2884      {      {
2885        int i;        int nsocks = 0;
2886          SELECT_TYPE orfds = *rfds;
2887    
2888          EventTimeout timeout_sec =
2889            (timeout
2890             ? (EMACS_SECS (*timeout) * kEventDurationSecond
2891                + EMACS_USECS (*timeout) * kEventDurationMicrosecond)
2892             : kEventDurationForever);
2893    
2894        for (i = 1; i < n; i++)        for (i = 1; i < n; i++)
2895          if (FD_ISSET (i, rfds))          if (FD_ISSET (i, rfds))
2896            break;            nsocks++;
       if (i == n)  
         {  
           EventTimeout timeout_sec =  
             (timeout  
              ? (EMACS_SECS (*timeout) * kEventDurationSecond  
                 + EMACS_USECS (*timeout) * kEventDurationMicrosecond)  
              : kEventDurationForever);  
2897    
2898          if (nsocks == 0)
2899            {
2900            BLOCK_INPUT;            BLOCK_INPUT;
2901            err = ReceiveNextEvent (0, NULL, timeout_sec,            err = ReceiveNextEvent (0, NULL, timeout_sec,
2902                                    kEventLeaveInQueue, NULL);                                    kEventLeaveInQueue, NULL);
2903            UNBLOCK_INPUT;            UNBLOCK_INPUT;
2904            if (err == noErr)            if (err == noErr)
2905              {              {
               FD_ZERO (rfds);  
2906                FD_SET (0, rfds);                FD_SET (0, rfds);
2907                return 1;                return 1;
2908              }              }
2909            else            else
2910              return 0;              return 0;
2911          }          }
     }  
2912    
2913    if (timeout)        /* Avoid initial overhead of RunLoop setup for the case that
2914      {           some input is already available.  */
2915        remaining_time = *timeout;        EMACS_SET_SECS_USECS (select_timeout, 0, 0);
2916        EMACS_GET_TIME (now);        r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout);
2917        EMACS_ADD_TIME (end_time, now, remaining_time);        if (r != 0 || timeout_sec == 0.0)
2918      }          return r;
2919    FD_CLR (0, rfds);  
2920    do        *rfds = orfds;
2921      {  
2922        EMACS_TIME select_timeout;  #ifdef SELECT_USE_CFSOCKET
2923        SELECT_TYPE orfds = *rfds;        if (timeout_sec > 0 && timeout_sec <= SELECT_TIMEOUT_THRESHOLD_RUNLOOP)
2924        int r;          goto poll_periodically;
2925    
2926        EMACS_SET_SECS_USECS (select_timeout, 0, 20000);        {
2927            CFRunLoopRef runloop =
2928              (CFRunLoopRef) GetCFRunLoopFromEventLoop (GetCurrentEventLoop ());
2929            EventTypeSpec specs[] = {{EVENT_CLASS_SOCK, 0}};
2930    #ifdef SELECT_INVALIDATE_CFSOCKET
2931            CFSocketRef *shead, *s;
2932    #else
2933            CFRunLoopSourceRef *shead, *s;
2934    #endif
2935    
2936        if (timeout && EMACS_TIME_LT (remaining_time, select_timeout))          BLOCK_INPUT;
         select_timeout = remaining_time;  
2937    
2938        r = select (n, &orfds, wfds, efds, &select_timeout);  #ifdef SELECT_INVALIDATE_CFSOCKET
2939        BLOCK_INPUT;          shead = xmalloc (sizeof (CFSocketRef) * nsocks);
2940        err = ReceiveNextEvent (0, NULL, kEventDurationNoWait,  #else
2941                                kEventLeaveInQueue, NULL);          shead = xmalloc (sizeof (CFRunLoopSourceRef) * nsocks);
2942        UNBLOCK_INPUT;  #endif
2943        if (r > 0)          s = shead;
2944          {          for (i = 1; i < n; i++)
2945            *rfds = orfds;            if (FD_ISSET (i, rfds))
           if (err == noErr)  
2946              {              {
2947                FD_SET (0, rfds);                CFSocketRef socket =
2948                r++;                  CFSocketCreateWithNative (NULL, i, kCFSocketReadCallBack,
2949                                              socket_callback, NULL);
2950                  CFRunLoopSourceRef source =
2951                    CFSocketCreateRunLoopSource (NULL, socket, 0);
2952    
2953    #ifdef SELECT_INVALIDATE_CFSOCKET
2954                  CFSocketSetSocketFlags (socket, 0);
2955    #endif
2956                  CFRunLoopAddSource (runloop, source, kCFRunLoopDefaultMode);
2957    #ifdef SELECT_INVALIDATE_CFSOCKET
2958                  CFRelease (source);
2959                  *s = socket;
2960    #else
2961                  CFRelease (socket);
2962                  *s = source;
2963    #endif
2964                  s++;
2965              }              }
           return r;  
         }  
       else if (err == noErr)  
         {  
           FD_ZERO (rfds);  
           FD_SET (0, rfds);  
           return 1;  
         }  
2966    
2967        if (timeout)          err = ReceiveNextEvent (0, NULL, timeout_sec, kEventLeaveInQueue, NULL);
2968          {  
2969            EMACS_GET_TIME (now);          do
2970            EMACS_SUB_TIME (remaining_time, end_time, now);            {
2971          }              --s;
2972    #ifdef SELECT_INVALIDATE_CFSOCKET
2973                CFSocketInvalidate (*s);
2974    #else
2975                CFRunLoopRemoveSource (runloop, *s, kCFRunLoopDefaultMode);
2976    #endif
2977                CFRelease (*s);
2978              }
2979            while (s != shead);
2980    
2981            xfree (shead);
2982    
2983            if (err)
2984              {
2985                FD_ZERO (rfds);
2986                r = 0;
2987              }
2988            else
2989              {
2990                FlushEventsMatchingListFromQueue (GetCurrentEventQueue (),
2991                                                  GetEventTypeCount (specs),
2992                                                  specs);
2993                EMACS_SET_SECS_USECS (select_timeout, 0, 0);
2994                r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout);
2995              }
2996    
2997            UNBLOCK_INPUT;
2998    
2999            return r;
3000          }
3001    #endif  /* SELECT_USE_CFSOCKET */
3002      }      }
   while (!timeout || EMACS_TIME_LT (now, end_time));  
3003    
3004    return 0;   poll_periodically:
3005      {
3006        EMACS_TIME end_time, now, remaining_time;
3007        SELECT_TYPE orfds = *rfds, owfds, oefds;
3008    
3009        if (wfds)
3010          owfds = *wfds;
3011        if (efds)
3012          oefds = *efds;
3013        if (timeout)
3014          {
3015            remaining_time = *timeout;
3016            EMACS_GET_TIME (now);
3017            EMACS_ADD_TIME (end_time, now, remaining_time);
3018          }
3019    
3020        do
3021          {
3022            EMACS_SET_SECS_USECS (select_timeout, 0, SELECT_POLLING_PERIOD_USEC);
3023            if (timeout && EMACS_TIME_LT (remaining_time, select_timeout))
3024              select_timeout = remaining_time;
3025            r = select_and_poll_event (n, rfds, wfds, efds, &select_timeout);
3026            if (r != 0)
3027              return r;
3028    
3029            *rfds = orfds;
3030            if (wfds)
3031              *wfds = owfds;
3032            if (efds)
3033              *efds = oefds;
3034    
3035            if (timeout)
3036              {
3037                EMACS_GET_TIME (now);
3038                EMACS_SUB_TIME (remaining_time, end_time, now);
3039              }
3040          }
3041        while (!timeout || EMACS_TIME_LT (now, end_time));
3042    
3043        FD_ZERO (rfds);
3044        if (wfds)
3045          FD_ZERO (wfds);
3046        if (efds)
3047          FD_ZERO (efds);
3048        return 0;
3049      }
3050  }  }
3051    
3052  /* Set up environment variables so that Emacs can correctly find its  /* Set up environment variables so that Emacs can correctly find its
# Line 3043  syms_of_mac () Line 3192  syms_of_mac ()
3192    defsubr (&Smac_paste_function);    defsubr (&Smac_paste_function);
3193    defsubr (&Smac_cut_function);    defsubr (&Smac_cut_function);
3194    defsubr (&Sx_selection_exists_p);    defsubr (&Sx_selection_exists_p);
3195      defsubr (&Smac_clear_font_name_table);
3196    
3197    defsubr (&Sdo_applescript);    defsubr (&Sdo_applescript);
3198    defsubr (&Smac_file_name_to_posix);    defsubr (&Smac_file_name_to_posix);

Legend:
Removed from v.1.24  
changed lines
  Added in v.1.25

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26