From http://www.jwz.org/xscreensaver/xscreensaver-5.18.tar.gz
[xscreensaver] / OSX / jwxyz-timers.m
index ec6f4394f73ec1d87b3aec925a9d523ffb247d06..be31b2dcf57c41eccef1ffd0a37095c7f6bf6f4d 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 2006 Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 2006-2012 Jamie Zawinski <jwz@jwz.org>
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
 /* This is the OSX implementation of Xt timers, for libjwxyz.
  */
 
-#import <stdlib.h>
-#import <Cocoa/Cocoa.h>
-#import "jwxyz.h"
-#import "jwxyz-timers.h"
-
 //#define DEBUG_TIMERS
 //#define DEBUG_SOURCES
 
 #undef USE_COCOA_SOURCES
 
 
+#import <stdlib.h>
+
+#ifdef USE_COCOA_SOURCES
+# import <Cocoa/Cocoa.h>
+#endif
+
+#import "jwxyz.h"
+#import "jwxyz-timers.h"
+
+
+
 #ifdef DEBUG_TIMERS
 # define LOGT(str,arg1,arg2) NSLog(str,arg1,arg2)
 #else
 # define LOGI(str,arg1,arg2,arg3)
 #endif
 
+#define ASSERT_RET(C,S) do {                    \
+    if (!(C)) {                                 \
+      jwxyz_abort ("jwxyz-timers: %s",(S));     \
+      return;                                   \
+ }} while(0)
+
 
 XtAppContext
 XtDisplayToApplicationContext (Display *dpy)
@@ -80,7 +92,7 @@ jwxyz_timer_retain (const void *arg)
 {
   struct jwxyz_XtIntervalId *data = (struct jwxyz_XtIntervalId *) arg;
   data->refcount++;
-  LOGT(@"timer  0x%08X: retain %d\n", (unsigned int) data, data->refcount);
+  LOGT(@"timer  0x%08X: retain %d", (unsigned int) data, data->refcount);
   return arg;
 }
 
@@ -89,8 +101,8 @@ jwxyz_timer_release (const void *arg)
 {
   struct jwxyz_XtIntervalId *data = (struct jwxyz_XtIntervalId *) arg;
   data->refcount--;
-  LOGT(@"timer  0x%08X: release %d\n", (unsigned int) data, data->refcount);
-  if (data->refcount < 0) abort();
+  LOGT(@"timer  0x%08X: release %d", (unsigned int) data, data->refcount);
+  ASSERT_RET (data->refcount >= 0, "double free");
   if (data->refcount == 0) free (data);
 }
 
@@ -99,7 +111,7 @@ jwxyz_source_retain (const void *arg)
 {
   struct jwxyz_XtInputId *data = (struct jwxyz_XtInputId *) arg;
   data->refcount++;
-  LOGI(@"source 0x%08X %2d: retain %d\n", (unsigned int) data, data->fd, 
+  LOGI(@"source 0x%08X %2d: retain %d", (unsigned int) data, data->fd, 
        data->refcount);
   return arg;
 }
@@ -109,9 +121,9 @@ jwxyz_source_release (const void *arg)
 {
   struct jwxyz_XtInputId *data = (struct jwxyz_XtInputId *) arg;
   data->refcount--;
-  LOGI(@"source 0x%08X %2d: release %d\n", (unsigned int) data, data->fd,
+  LOGI(@"source 0x%08X %2d: release %d", (unsigned int) data, data->fd,
        data->refcount);
-  if (data->refcount < 0) abort();
+  ASSERT_RET (data->refcount >= 0, "double free");
   if (data->refcount == 0) {
 # ifdef USE_COCOA_SOURCES
     if (data->socket)
@@ -130,7 +142,7 @@ static void
 jwxyz_timer_cb (CFRunLoopTimerRef timer, void *arg)
 {
   struct jwxyz_XtIntervalId *data = (struct jwxyz_XtIntervalId *) arg;
-  LOGT(@"timer  0x%08X: fire\n", (unsigned int) data, 0);
+  LOGT(@"timer  0x%08X: fire", (unsigned int) data, 0);
   data->cb (data->closure, &data);
 
   // Our caller (__CFRunLoopDoTimer) will now call CFRunLoopTimerInvalidate,
@@ -159,18 +171,18 @@ jwxyz_source_cb (CFSocketRef s, CFSocketCallBackType type,
 {
   struct jwxyz_XtInputId *data = (struct jwxyz_XtInputId *) info;
 
-  if (type != kCFSocketReadCallBack) abort();
-  if (call_data != 0) abort();  // not used for kCFSocketRead
+  ASSERT_RET (type == kCFSocketReadCallBack, "unnknown type");
+  ASSERT_RET (!call_data, "no call data");  // not used for kCFSocketRead
 
   // We are sometimes called when there is not, in fact, data available!
   // So don't call data->cb if we're being fed a pack of lies.
   //
   if (! input_available_p (data->fd)) {
-    LOGI(@"source 0x%08X %2d: false alarm!\n", (unsigned int) data, data->fd, 0);
+    LOGI(@"source 0x%08X %2d: false alarm!", (unsigned int) data, data->fd, 0);
     return;
   }
 
-  LOGI(@"source 0x%08X %2d: fire\n", (unsigned int) data, data->fd, 0);
+  LOGI(@"source 0x%08X %2d: fire", (unsigned int) data, data->fd, 0);
 
   data->cb (data->closure, &data->fd, &data);
 }
@@ -187,7 +199,7 @@ XtAppAddTimeOut (XtAppContext app, unsigned long msecs,
   data->cb = cb;
   data->closure = closure;
 
-  LOGT(@"timer  0x%08X: alloc %d\n", (unsigned int) data, msecs);
+  LOGT(@"timer  0x%08X: alloc %d", (unsigned int) data, msecs);
   
   CFRunLoopTimerContext ctx = { 0, };
   ctx.info    = data;
@@ -211,10 +223,9 @@ XtAppAddTimeOut (XtAppContext app, unsigned long msecs,
 void
 XtRemoveTimeOut (XtIntervalId id)
 {
-  LOGT(@"timer  0x%08X: remove\n", (unsigned int) id, 0);
-  if (id->refcount <= 0) abort();
-  if (!id->cftimer) abort();
-
+  LOGT(@"timer  0x%08X: remove", (unsigned int) id, 0);
+  ASSERT_RET (id->refcount > 0, "already freed");
+  ASSERT_RET (id->cftimer, "timers corrupted");
   CFRunLoopRemoveTimer (CFRunLoopGetCurrent(), id->cftimer,
                         kCFRunLoopCommonModes);
   CFRunLoopTimerInvalidate (id->cftimer);
@@ -247,8 +258,8 @@ static void
 jwxyz_source_select (XtInputId id)
 {
   jwxyz_sources_data *td = display_sources_data (app_to_display (id->app));
-  if (id->fd <= 0 || id->fd >= FD_SETSIZE) abort();
-  if (td->ids[id->fd]) abort();
+  ASSERT_RET (id->fd > 0 && id->fd < FD_SETSIZE, "fd out of range");
+  ASSERT_RET (td->ids[id->fd] == 0, "sources corrupted");
   td->ids[id->fd] = id;
   td->count++;
 }
@@ -257,9 +268,9 @@ static void
 jwxyz_source_deselect (XtInputId id)
 {
   jwxyz_sources_data *td = display_sources_data (app_to_display (id->app));
-  if (td->count <= 0) abort();
-  if (id->fd <= 0 || id->fd >= FD_SETSIZE) abort();
-  if (td->ids[id->fd] != id) abort();
+  ASSERT_RET (td->count > 0, "sources corrupted");
+  ASSERT_RET (id->fd > 0 && id->fd < FD_SETSIZE, "fd out of range");
+  ASSERT_RET (td->ids[id->fd] == id, "sources corrupted");
   td->ids[id->fd] = 0;
   td->count--;
 }
@@ -282,14 +293,14 @@ jwxyz_sources_run (jwxyz_sources_data *td)
     }
   }
 
-  if (!max) abort();
+  ASSERT_RET (max > 0, "no fds");
 
   if (0 < select (max+1, &fds, NULL, NULL, &tv)) {
     for (i = 0; i < FD_SETSIZE; i++) {
       if (FD_ISSET (i, &fds)) {
         XtInputId id = td->ids[i];
-        if (!id || !id->cb) abort();
-        if (id->fd != i) abort();
+        ASSERT_RET (id && id->cb, "sources corrupted");
+        ASSERT_RET (id->fd == i, "sources corrupted");
         id->cb (id->closure, &id->fd, &id);
       }
     }
@@ -309,7 +320,7 @@ XtAppAddInput (XtAppContext app, int fd, XtPointer flags,
   data->fd = fd;
   data->closure = closure;
 
-  LOGI(@"source 0x%08X %2d: alloc\n", (unsigned int) data, data->fd, 0);
+  LOGI(@"source 0x%08X %2d: alloc", (unsigned int) data, data->fd, 0);
 
 # ifdef USE_COCOA_SOURCES
 
@@ -346,11 +357,11 @@ XtAppAddInput (XtAppContext app, int fd, XtPointer flags,
 void
 XtRemoveInput (XtInputId id)
 {
-  LOGI(@"source 0x%08X %2d: remove\n", (unsigned int) id, id->fd, 0);
-  if (id->refcount <= 0) abort();
+  LOGI(@"source 0x%08X %2d: remove", (unsigned int) id, id->fd, 0);
+  ASSERT_RET (id->refcount > 0, "sources corrupted");
 # ifdef USE_COCOA_SOURCES
-  if (! id->cfsource) abort();
-  if (! id->socket) abort();
+  ASSERT_RET (id->cfsource, "sources corrupted");
+  ASSERT_RET (id->socket, "sources corrupted");
 
   CFRunLoopRemoveSource (CFRunLoopGetCurrent(), id->cfsource,
                          kCFRunLoopCommonModes);
@@ -369,7 +380,7 @@ void
 jwxyz_XtRemoveInput_all (Display *dpy)
 {
 # ifdef USE_COCOA_SOURCES
-  abort();
+  ASSERT_RET (0, "unimplemented");
 # else  /* !USE_COCOA_SOURCES */
 
   jwxyz_sources_data *td = display_sources_data (dpy);
@@ -381,3 +392,17 @@ jwxyz_XtRemoveInput_all (Display *dpy)
 
 # endif /* !USE_COCOA_SOURCES */
 }
+
+
+XtInputMask
+XtAppPending (XtAppContext app)
+{
+  return XtIMAlternateInput;  /* just always say yes */
+}
+
+void
+XtAppProcessEvent (XtAppContext app, XtInputMask mask)
+{
+  jwxyz_sources_data *td = display_sources_data (app_to_display (app));
+  jwxyz_sources_run (td);
+}