--- icewm-1.0.4-pristine/README.icefx	Sat Nov 25 00:26:12 2000
+++ icewm-1.0.4-dev/README.icefx	Sat Nov 25 00:24:52 2000
@@ -0,0 +1,12 @@
+IceFX
+=====
+
+./configure --enable-guievents
+
+make PROGRAMS=icesound
+make PROGRAMS=icecursor
+
+copy some sound and cursors to ~/.icewm/sounds/ and ~/.icewm/cursors/
+
+enjoy ./src/icesound and ./src/icecursor
+
--- icewm-1.0.4-pristine/src/Makefile	Sun Jun 11 20:19:07 2000
+++ icewm-1.0.4-dev/src/Makefile	Sat Nov 25 00:25:17 2000
@@ -44,6 +44,8 @@
 
 ICESOUNDOBJS = icesound.o misc.o 
 
+ICECURSOROBJS = icecursor.o misc.o 
+
 ICECLOCKOBJS = $(COREOBJS) \
           iceclock.o aclock.o
 
@@ -73,7 +75,7 @@
 ICESKTOBJS = $(COREOBJS) \
              iceskt.o
 
-PROGRAMS    = icewm$(EXEEXT) genpref$(EXEEXT) icewmhint$(EXEEXT) icewmbg$(EXEEXT) #icelist$(EXEEXT) #iceclock$(EXEEXT) #icebar$(EXEEXT) #icesound$(EXEEXT) #icerun$(EXEEXT)
+PROGRAMS    = icewm$(EXEEXT) genpref$(EXEEXT) icewmhint$(EXEEXT) icewmbg$(EXEEXT) icesound$(EXEEXT) icecursor$(EXEEXT) #icelist$(EXEEXT) #iceclock$(EXEEXT) #icebar$(EXEEXT) #icerun$(EXEEXT)
 
 .SUFFIXES:
 .SUFFIXES: .cc .o .h
@@ -107,7 +109,11 @@
 
 icesound$(EXEEXT): $(ICESOUNDOBJS)
 	-@rm -f $@
-	$(LD) -o $@ $(LFLAGS) $(ICESOUNDOBJS) $(LIBS)
+	$(LD) -o $@ $(LFLAGS) $(ICESOUNDOBJS) $(LIBS) -lesd
+
+icecursor$(EXEEXT): $(ICECURSOROBJS)
+	-@rm -f $@
+	$(LD) -o $@ $(LFLAGS) $(ICECURSOROBJS) $(LIBS) -lXmu
 
 iceclock$(EXEEXT): $(ICECLOCKOBJS)
 	-@rm -f $@
@@ -212,6 +218,7 @@
 iceskt.o: iceskt.cc config.h yapp.h ywindow.h ypaint.h ysocket.h \
  debug.h
 icesound.o: icesound.cc guievent.h
+icecursor.o: icecursor.cc guievent.h
 iceview.o: iceview.cc config.h ylib.h base.h debug.h ylistbox.h \
  ywindow.h ypaint.h yscrollbar.h ytimer.h yscrollview.h ymenu.h \
  ypopup.h yapp.h sysdep.h yaction.h
--- icewm-1.0.4-pristine/src/icecursor.cc	Sat Nov 25 00:26:22 2000
+++ icewm-1.0.4-dev/src/icecursor.cc	Sat Nov 25 00:28:54 2000
@@ -0,0 +1,455 @@
+/*
+ * IceWM - IceCursor
+ *
+ * Copyright (C) 2000 Christian W. Zuckschwerdt
+ *
+ * animate the X cursor each time a specific GUI event occures
+ * (see guievent.h)
+ * for now cursors and masks need to be in LIBDIR/cursors
+ *
+ * 2000-10-01 Christian W. Zuckschwerdt <zany@triq.net>
+ */
+
+/* CONFIG_GUIEVENTS or bail out */
+#ifndef CONFIG_GUIEVENTS
+ you need to configure with guievents
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <X11/Xproto.h>
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xresource.h>
+#include <X11/cursorfont.h>
+#include <X11/keysym.h>
+#include <X11/xpm.h>
+#include <signal.h>
+#include <audiofile.h>
+#include <esd.h>
+#include <time.h>
+
+#define GUI_EVENT_NAMES
+#include "guievent.h"
+#include "base.h"
+#define NUM_OF_GUIEVENTS (sizeof(gui_events)/sizeof(gui_events[0]))
+#define NUM_OF_FRAMES 8
+
+/* needed in FixupState */
+#define Dynamic 1
+
+/* int XmuCursorNameToIndex (char *name); */
+#include <X11/Xmu/CurUtil.h>
+
+static char *program_name = NULL;
+
+char *displayName = 0;
+Display *display = 0;
+Window root = 0;
+
+Atom _GUI_EVENT;;
+
+char default_cursor_name[] = "left_ptr"; /* see also: cursorfont.h */
+Cursor cursors [NUM_OF_GUIEVENTS][NUM_OF_FRAMES];
+
+Display *dpy;
+int screen;
+Window root1;
+char *fore_color = NULL;
+char *back_color = NULL;
+int reverse = 0;
+int save_colors = 0;
+int unsave_past = 0;
+Pixmap save_pixmap = (Pixmap)None;
+
+void read_cursors();
+int set_cursor(Cursor cursor);
+int file_pointer(char *cursor_file, char *cursor_mask);
+int normal_pointer(const char *cursor_name);
+void FixupState();
+Cursor CreateCursorFromFiles(const char *cursor_file, const char *mask_file);
+Cursor CreateCursorFromName (const char *name);
+XColor NameToXColor(const char *name, unsigned long pixel);
+Pixmap ReadBitmapFile(const char *filename, unsigned int *width, unsigned int *height, int *x_hot, int *y_hot);
+
+
+int main(int argc, char *argv[])
+{
+
+    program_name = strrchr(argv[0], '/');
+    if (program_name) program_name++; else program_name = argv[0];
+
+    if (!(display = XOpenDisplay(displayName)))
+      {
+	fprintf(stderr, "can't open display: %s", displayName);
+	exit(1);
+      }
+
+    root = RootWindow(display, DefaultScreen(display));
+
+    screen = DefaultScreen(display); 
+    dpy = display;
+    read_cursors();
+
+    _GUI_EVENT = XInternAtom(display, XA_GUI_EVENT_NAME, False);
+
+    XSelectInput(display, root, PropertyChangeMask);
+
+    while (1)
+      {
+        XEvent xev;
+        time_t last, now;
+
+        XNextEvent(display, &xev);
+
+        switch (xev.type) {
+        case PropertyNotify:
+            if (xev.xproperty.atom == _GUI_EVENT)
+	      {
+
+	        /* act at most every other second */
+	        /*last = now;
+		now = time(NULL);
+		if (last+1 < now)*/
+
+		    if (xev.xproperty.state == PropertyNewValue)
+		      {
+			Atom type;
+			int format;
+			unsigned long nitems, lbytes;
+			unsigned char *propdata;
+			int d = -1;
+
+			if (XGetWindowProperty(display, root,
+					       _GUI_EVENT, 0, 3,
+					       False, _GUI_EVENT,
+					       &type, &format,
+					       &nitems, &lbytes,
+					       &propdata) == Success)
+			    if (propdata)
+			      {
+				d = *(char *)propdata;
+				XFree(propdata);
+			      }
+			for (unsigned int i = 0; i < sizeof(gui_events)/sizeof(gui_events[0]); i++)
+			  {
+			    if (gui_events[i].type == d)
+			      {
+				puts(gui_events[i].name);
+				/*			    
+				if (geLaunchApp == i)
+				  {
+				    /* Restore normal pointer * /
+				    fore_color = NULL;
+				    normal_pointer("watch");
+				  }
+				else
+				  {
+				    /* Restore normal pointer * /
+				    fore_color = NULL;
+				    normal_pointer(default_cursor_name);
+				  }
+				*/
+				
+				if (1) // cursors[i][0])
+				  {
+			        /* Animate cursor */
+				    for (int n = 0; n < NUM_OF_FRAMES; n++)
+				      {
+					// !!! TODO: which colors?
+					fore_color = "gold";
+					set_cursor(cursors[i][n]);
+					usleep(100000);
+				      }
+				/* Restore normal pointer */
+				    fore_color = NULL;
+				    normal_pointer(default_cursor_name);
+				  }
+				break;
+			      }
+			  }
+		      }
+	      }
+            break;
+        }
+      }
+}
+
+void read_cursors()
+{
+    const char *homeDir = getenv("HOME");
+    char *path, *libpath;
+    path = strJoin(homeDir, "/.icewm/cursors/", NULL);
+    libpath = strJoin(LIBDIR, "/cursors/", NULL);
+
+    char cursor[1024], mask[1024];
+    char *cursor_path, *mask_path;
+    int i, n;
+    
+    for (i=0; i < (int)NUM_OF_GUIEVENTS; i++)
+      {
+	for (n=0; n < NUM_OF_FRAMES; n++)
+	  {
+	    sprintf(cursor, "%s_cursor_%d.xbm", gui_events[i].name, n+1);
+	    sprintf(mask, "%s_mask_%d.xbm", gui_events[i].name, n+1);
+	    cursor_path = strJoin(path, cursor, NULL);
+	    mask_path = strJoin(path, mask, NULL);
+	    if ((access(cursor_path, R_OK) == 0) &&
+		(access(mask_path, R_OK) == 0))
+	      {
+printf("found %s\n", cursor_path);
+		// !!! TODO: set colors?
+		fore_color = "gold";
+		cursors[i][n] = CreateCursorFromFiles(cursor_path, mask_path); 
+	      }
+	  }
+      }
+}
+
+int file_pointer(char *cursor_file, char *cursor_mask)
+{
+    /* Variables */
+    Cursor cursor;
+
+    /* Init display */
+    dpy = XOpenDisplay(NULL); 
+    if (!dpy)
+      { 
+	fprintf(stderr, "%s:  unable to open display '%s'\n", 
+		program_name, XDisplayName (NULL)); 
+	exit (2); 
+      } 
+    screen = DefaultScreen(dpy); 
+    root1 = RootWindow(dpy, screen); 
+
+    /* Set busy-cursor */
+    cursor = CreateCursorFromFiles(cursor_file, cursor_mask); 
+    XDefineCursor(dpy, root1, cursor);
+    XFreeCursor(dpy, cursor); 
+
+    FixupState(); 
+    XCloseDisplay(dpy); 
+    return (0);
+}
+
+int set_cursor(Cursor cursor)
+{
+    /* Init display */
+    dpy = XOpenDisplay(NULL); 
+    if (!dpy)
+      { 
+	fprintf(stderr, "%s:  unable to open display '%s'\n", 
+		program_name, XDisplayName (NULL)); 
+	exit (2); 
+      } 
+    screen = DefaultScreen(dpy); 
+    root1 = RootWindow(dpy, screen); 
+
+    /* Set -cursor */
+    XDefineCursor(dpy, root1, cursor);
+
+    FixupState(); 
+    XCloseDisplay(dpy); 
+    return (0);
+}
+
+int normal_pointer(const char *cursor_name)
+{
+    /* Variables */
+    Cursor cursor;
+
+    /* Init display */
+    dpy = XOpenDisplay(NULL); 
+    if (!dpy)
+      { 
+	fprintf(stderr, "%s:  unable to open display '%s'\n", 
+		program_name, XDisplayName (NULL)); 
+	exit (2); 
+      } 
+    screen = DefaultScreen(dpy); 
+    root1 = RootWindow(dpy, screen); 
+
+    /* Restore normal pointer */
+    cursor = CreateCursorFromName (cursor_name);
+    if (cursor)
+      {
+	XDefineCursor (dpy, root1, cursor);
+	XFreeCursor (dpy, cursor);
+      }
+
+    FixupState(); 
+    XCloseDisplay(dpy); 
+    return (0);
+}
+
+
+/* Free past incarnation if needed, and retain state if needed. */
+void FixupState()
+{
+    Atom prop, type;
+    int format;
+    unsigned long length, after;
+    unsigned char *data;
+    /*
+    if (!(DefaultVisual(dpy, screen)->class & Dynamic))
+    unsave_past = 0;*/
+    if (!unsave_past && !save_colors)
+	return;
+    prop = XInternAtom(dpy, "_XSETROOT_ID", False);
+    if (unsave_past)
+      {    
+	(void)XGetWindowProperty(dpy, root1, prop, 0L, 1L, True,
+				 AnyPropertyType,
+				 &type, &format, &length, &after, &data);
+	if ((type == XA_PIXMAP) && (format == 32) &&
+	    (length == 1) && (after == 0))
+	    XKillClient(dpy, *((Pixmap *)data));
+	else if (type != None)
+	    fprintf(stderr, "%s: warning: _XSETROOT_ID property is garbage\n",
+		    program_name);
+      }
+    if (save_colors)
+      {
+	if (!save_pixmap)
+	    save_pixmap = XCreatePixmap(dpy, root1, 1, 1, 1);
+	XChangeProperty(dpy, root1, prop, XA_PIXMAP, 32, PropModeReplace,
+			(unsigned char *) &save_pixmap, 1);
+	XSetCloseDownMode(dpy, RetainPermanent);
+      }
+}
+
+
+/*
+ * CreateCursorFromFiles: make a cursor of the right colors from two bitmap
+ *                        files.
+ */
+#define BITMAP_HOT_DEFAULT 8
+
+Cursor CreateCursorFromFiles(const char *cursor_file, const char *mask_file)
+{
+    Pixmap cursor_bitmap, mask_bitmap;
+    unsigned int width, height, ww, hh;
+    int x_hot, y_hot;
+    Cursor cursor;
+    XColor fg, bg, temp;
+
+    fg = NameToXColor(fore_color, BlackPixel(dpy, screen));
+    bg = NameToXColor(back_color, WhitePixel(dpy, screen));
+    if (reverse)
+      {
+	temp = fg; fg = bg; bg = temp;
+      }
+
+    cursor_bitmap = ReadBitmapFile(cursor_file, &width, &height, &x_hot, &y_hot);
+    mask_bitmap = ReadBitmapFile(mask_file, &ww, &hh, (int *)NULL, (int *)NULL);
+
+    if (width != ww || height != hh)
+      {
+	fprintf(stderr, 
+"%s: dimensions of cursor bitmap and cursor mask bitmap are different\n", 
+		program_name);
+	exit(1);
+	/*NOTREACHED*/
+      }
+
+    if ((x_hot == -1) && (y_hot == -1))
+      {
+	x_hot = BITMAP_HOT_DEFAULT;
+	y_hot = BITMAP_HOT_DEFAULT;
+      }
+    if ((x_hot < 0) || (x_hot >= (int)width) ||
+	(y_hot < 0) || (y_hot >= (int)height))
+      {
+	fprintf(stderr, "%s: hotspot is outside cursor bounds\n", program_name);
+	exit(1);
+	/*NOTREACHED*/
+      }
+
+    cursor = XCreatePixmapCursor(dpy, cursor_bitmap, mask_bitmap, &fg, &bg,
+				 (unsigned int)x_hot, (unsigned int)y_hot);
+    XFreePixmap(dpy, cursor_bitmap);
+    XFreePixmap(dpy, mask_bitmap);
+
+    return(cursor);
+}
+
+/*
+ * CreateCursorFromName: Return cursor with given name
+ * global variables:
+ *  dpy, screen, fore_color, back_color, reverse
+ */
+Cursor CreateCursorFromName (const char *name)
+{
+    XColor fg, bg, temp;
+    int	    i;
+    Font    fid;
+
+    fg = NameToXColor(fore_color, BlackPixel(dpy, screen));
+    bg = NameToXColor(back_color, WhitePixel(dpy, screen));
+    if (reverse)
+      {
+	temp = fg; fg = bg; bg = temp;
+      }
+    i = XmuCursorNameToIndex (name);
+    if (i == -1)
+	return (Cursor) NULL;
+    fid = XLoadFont (dpy, "cursor");
+    if (!fid)
+	return (Cursor) NULL;
+    return XCreateGlyphCursor (dpy, fid, fid,
+			       i, i+1, &fg, &bg);
+}
+
+
+/*
+ * NameToXColor: Convert the name of a color to its Xcolor value.
+ */
+XColor NameToXColor(const char *name, unsigned long pixel)
+{
+    XColor c;
+    
+    if (!name || !*name)
+      {
+	c.pixel = pixel;
+	XQueryColor(dpy, DefaultColormap(dpy, screen), &c);
+      }
+    else if (!XParseColor(dpy, DefaultColormap(dpy, screen), name, &c))
+      {
+	fprintf(stderr, "%s: unknown color or bad color format: %s\n",
+			program_name, name);
+	exit(1);
+	/*NOTREACHED*/
+      }
+    return(c);
+}
+
+
+Pixmap ReadBitmapFile(const char *filename, unsigned int *width, unsigned int *height, int *x_hot, int *y_hot)
+{
+    Pixmap bitmap;
+    int status;
+
+    status = XReadBitmapFile(dpy, root, filename, width,
+			     height, &bitmap, x_hot, y_hot);
+    if (status == BitmapSuccess)
+      return(bitmap);
+    else if (status == BitmapOpenFailed)
+	fprintf(stderr, "%s: can't open file: %s\n", program_name, filename);
+    else if (status == BitmapFileInvalid)
+	fprintf(stderr, "%s: bad bitmap format file: %s\n",
+			program_name, filename);
+    else
+	fprintf(stderr, "%s: insufficient memory for bitmap: %s",
+			program_name, filename);
+    exit(1);
+    /*NOTREACHED*/
+}
--- icewm-1.0.4-pristine/src/icesound.cc	Sun Feb 13 16:57:30 2000
+++ icewm-1.0.4-dev/src/icesound.cc	Sat Nov 25 00:28:18 2000
@@ -1,10 +1,18 @@
 /*
- * IceWM
+ * IceWM - IceSound
  *
- * Copyright (C) 1997,1998 Marko Macek
- * EsounD Hack by CW Zuckschwerdt
+ * Based on IceWM code Copyright (C) 1997,1998 Marko Macek
+ * Christian W. Zuckschwerdt  <zany@triq.net>  2000-10-02
+ *
+ * Output options: /dev/dsp, ESD
+ * Is anyone interested in ALSA, ...etc? Nag me about your fav.
  */
 
+/* CONFIG_GUIEVENTS or bail out */
+#ifndef CONFIG_GUIEVENTS
+ you need to configure with guievents
+#endif
+
 #define ESD
 
 #include <assert.h>
@@ -21,31 +29,177 @@
 #include <X11/Xatom.h>
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
-#include <X11/Xresource.h>
-#include <X11/cursorfont.h>
-#include <X11/keysym.h>
-#include <X11/xpm.h>
 #include <signal.h>
-#include <audiofile.h>
+/* #include <audiofile.h> /* esd wraps af: not needed */
 #include <esd.h>
 
 #define GUI_EVENT_NAMES
 #include "guievent.h"
+#define GUIEVENTS (sizeof(gui_events)/sizeof(gui_events[0]))
+
+#include "base.h" /* strJoin */
 
 static char *program_name = NULL;
 
+#ifdef ESD
+
+char *esd_server = NULL; /* read as option */
+int esd = -1;
+int sample[GUIEVENTS];
+
+/* cache a sample in the server returns sample id, < 0 = error */
+int cache_sound(char *path, int sound)
+{
+    int ok;
+    ok = esd_file_cache( esd, program_name, path );
+    if (ok < 0)
+      {
+	printf( "%s: Error <%d> uploading. Name = %s:%s\n",
+		program_name, ok, program_name, path );
+	return ok;
+      }
+    sample[sound] = ok;
+    printf( "%s: Sample <%d> uploaded. Name = %s:%s\n",
+	    program_name, ok, program_name, path );
+    return ok;
+}
+
+/* uncache a sample from the server */
+int  uncache()
+{
+    int cnt = 0; 
+    for (int i = 0; i < (int)GUIEVENTS; i++)
+        if (sample[i] > 0) {
+	    esd_sample_free(esd, sample[i]);
+	    cnt++;
+	}
+    return cnt;
+}
+
+/*
+ * cache the sounds into the EsounD sever
+ * returns: number of loaded samples
+ */
+int cache()
+{
+    const char *homeDir = getenv("HOME");
+    char *path, *libpath;
+    path = strJoin(homeDir, "/.icewm/sounds/", NULL);
+    libpath = strJoin(LIBDIR, "/sounds/", NULL);
+    int cnt = 0;
+
+    char sound_file[1024];
+    char *sound_path;
+
+    for (int i = 0; i < (int)GUIEVENTS; i++)
+      {
+	sprintf(sound_file, "%s.wav", gui_events[i].name);
+	sound_path = strJoin(path, sound_file, NULL);
+	if (access(sound_path, R_OK) == 0)
+	  {
+	    cache_sound(sound_path, i);
+	    cnt++;
+	  }
+	else
+	  {
+	    sound_path = strJoin(libpath, sound_file, NULL);
+	    if (access(sound_path, R_OK) == 0)
+	      {
+		cache_sound(sound_path, i);
+		cnt++;
+	      }
+	  }
+      }
+    return cnt;
+}
+
+#endif
+
+/* play a sound sample */
+void sound_play(int sound)
+{
+#ifdef ESD
+    if (sample[ sound ] > 0 )
+        esd_sample_play(esd, sample[ sound ]);
+#else
+    for (unsigned int i = 0; i < sizeof(gui_events)/sizeof(gui_events[0]); i++)
+      {
+	if (gui_events[i].type == sound) {
+	    char s[1024];
+	    int ifd, ofd, n;
+	    // !!! TODO: search in (~/.icewm/)
+	    sprintf(s, "%s/sounds/%s.wav", LIBDIR, gui_events[i].name);
+
+	    if (access(s, R_OK) == 0) {
+	        ifd = open(s, O_RDONLY);
+		if (ifd == -1)
+		    exit(0);
+		ofd = open("/dev/dsp", O_WRONLY);
+		if (ofd == -1)
+		    exit(0);
+		while ((n = read(ifd, s, sizeof(s))) > 0)
+		    write(ofd, s, n);
+	    }
+	    break;
+	}
+      }
+#endif
+}
+
+volatile int terminate = 0;
+
+void clean_exit(int sig) {
+    signal(sig, SIG_DFL);
+    fprintf( stderr, "%s: received signal %d: terminating...\n",
+	     program_name, sig );
+    terminate = 1;
+    return;
+}
+
+/*
+ * Catch a restart signal and reload
+ */
+void sighup_handler(int sig)
+{
+#ifdef DEBUG
+    printf("%s: signal %d", program_name, sig);
+#endif
+#ifdef ESD
+    uncache();
+    cache();
+#endif
+}
+
+
 char *displayName = 0;
 Display *display = 0;
 Window root = 0;
+time_t lastev = 0; /* should really be  struct timeb */
 
 Atom _GUI_EVENT;;
 
 int main(int argc, char *argv[]) {
 
-    program_name = argv [0];
+    program_name = strrchr(argv[0], '/');
+    if (program_name) program_name++; else program_name = argv[0];
+
+    /* if we see any of these, terminate */
+    signal( SIGINT, clean_exit );
+    signal( SIGKILL, clean_exit );
+    signal( SIGPIPE, clean_exit );
+
+#ifdef ESD
+    for (int i = 0; i < (int)GUIEVENTS; i++)
+        sample[i] = -1;
+
+    esd = esd_open_sound( esd_server );
+    if ( esd <= 0 ) return 1;
+    cache();
+#endif
 
     if (!(display = XOpenDisplay(displayName))) {
-        fprintf(stderr, "can't open display: %s", displayName);
+        fprintf(stderr, "%s: can't open display: %s",
+		program_name, displayName);
         exit(1);
     }
 
@@ -55,12 +209,13 @@
 
     XSelectInput(display, root, PropertyChangeMask);
 
-    signal(SIGCHLD, SIG_IGN);
+    signal(SIGHUP, sighup_handler);
 
-    while (1) {
+    while (!terminate) {
         XEvent xev;
+	time_t now;
 
-        XNextEvent(display, &xev);
+        XNextEvent(display, &xev); /* blocks */
 
         switch (xev.type) {
         case PropertyNotify:
@@ -80,40 +235,32 @@
                             d = *(char *)propdata;
                             XFree(propdata);
                         }
-                    int pid = -1;
-                    if (pid > 0)
-                        kill(pid, SIGKILL);
-                    if (d != -1 && (pid = fork()) == 0) {
+		    if (geRestart == d) {
+		        printf("%s: recieved restart event.\n",
+			       program_name);
+#ifdef ESD
+			uncache();
+			cache();
+#endif
+		    }
+
+		    now = time(NULL); /* should be ftime(3) */
+
+                    if (now - lastev >0) {
+		        lastev = now;
                         for (unsigned int i = 0; i < sizeof(gui_events)/sizeof(gui_events[0]); i++) {
                             if (gui_events[i].type == d) {
                                 puts(gui_events[i].name);
-                                char s[1024];
-                                int ifd, ofd, n;
-                                // !!! TODO: search in (~/.icewm/)
-                                sprintf(s, "%s/sounds/%s.wav", LIBDIR, gui_events[i].name);
-
-                                if (access(s, R_OK) == 0) {
-#ifdef ESD
-                                    esd_play_file(program_name, s, 1);
-#else
-                                    ifd = open(s, O_RDONLY);
-                                    if (ifd == -1)
-                                        exit(0);
-                                    ofd = open("/dev/dsp", O_WRONLY);
-                                    if (ofd == -1)
-                                        exit(0);
-                                    while ((n = read(ifd, s, sizeof(s))) > 0)
-                                        write(ofd, s, n);
-#endif
-                                }
-                                break;
-                            }
+			    }
                         }
-                        exit(0);
+			sound_play( d );
                     }
                 }
             }
             break;
         }
     }
+#ifdef ESD
+    uncache();
+#endif
 }
