--- ./src/screen.c.orig-defcursor	Sun Mar  7 04:55:25 1999
+++ ./src/screen.c	Wed Mar 24 03:15:10 1999
@@ -677,7 +677,9 @@
 	return NULL;
     }
 
+#ifndef DEFINABLE_CURSOR
     XDefineCursor(dpy, scr->root_win, wCursor[WCUR_DEFAULT]);
+#endif
 
     /* screen descriptor for raster graphic library */
     rattr.flags = RC_RenderMode | RC_ColorsPerChannel;
--- ./src/wconfig.h.in.orig-defcursor	Wed Mar 24 03:15:10 1999
+++ ./src/wconfig.h.in	Wed Mar 24 03:15:10 1999
@@ -201,6 +201,11 @@
  */
 #undef WINDOW_BIRTH_ZOOM
 
+/*
+ * define DEFINABLE_CURSOR if you want WindowMaker's default cursor
+ * to be user-definable instead of using a hard-coded left_ptr.
+ */
+#define DEFINABLE_CURSOR
 
 /*
  *--------------------------------------------------------------------
--- ./src/defaults.c.orig-defcursor	Sun Mar  7 04:55:25 1999
+++ ./src/defaults.c	Wed Mar 24 03:15:10 1999
@@ -164,6 +164,11 @@
 
 static int updateUsableArea();
 
+#ifdef DEFINABLE_CURSOR
+extern Cursor wCursor[WCUR_LAST];
+static int getCursor();
+static int setCursor();
+#endif
 
 
 /*
@@ -687,6 +692,31 @@
          &wPreferences.title_shadow, getBool,  setJustify
     }
 #endif /* TITLE_TEXT_SHADOW */
+#ifdef DEFINABLE_CURSOR
+    ,{"NormalCursor", "(builtin, left_ptr)",	(void*)WCUR_ROOT,
+          NULL,				getCursor,	setCursor
+    }
+    ,{"MoveCursor", "(builtin, fleur)",		(void*)WCUR_MOVE,
+          NULL,				getCursor,	setCursor
+    }
+    ,{"ResizeCursor", "(builtin, sizing)",	(void*)WCUR_RESIZE,
+          NULL,				getCursor,	setCursor
+    }
+    ,{"WaitCursor", "(builtin, watch)",		(void*)WCUR_WAIT,
+          NULL,				getCursor,	setCursor
+    }
+#if 0
+    ,{"ArrowCursor", "(builtin, top_left_arrow)",	(void*)WCUR_ARROW,
+          NULL,				getCursor,	setCursor
+    }
+    ,{"QuestionCursor", "(builtin, question_arrow)",	(void*)WCUR_QUESTION,
+          NULL,				getCursor,	setCursor
+    }
+    ,{"TextCursor", "(builtin, xterm)",		(void*)WCUR_TEXT,
+          NULL,				getCursor,	setCursor
+    }
+#endif
+#endif /* DEFINABLE_CURSOR */
 };
 
 
@@ -2189,6 +2219,296 @@
 }
 
 
+#ifdef DEFINABLE_CURSOR
+
+# include <X11/cursorfont.h>
+typedef struct 
+{
+   char *name;
+   int id;
+} WCursorLookup;
+
+#define CURSOR_ID_NONE	(XC_num_glyphs)
+
+static WCursorLookup cursor_table[] =
+{
+    { "X_cursor",		XC_X_cursor },
+    { "arrow",			XC_arrow },
+    { "based_arrow_down",	XC_based_arrow_down },
+    { "based_arrow_up",		XC_based_arrow_up },
+    { "boat",			XC_boat },
+    { "bogosity",		XC_bogosity },
+    { "bottom_left_corner",	XC_bottom_left_corner },
+    { "bottom_right_corner",	XC_bottom_right_corner },
+    { "bottom_side",		XC_bottom_side },
+    { "bottom_tee",		XC_bottom_tee },
+    { "box_spiral",		XC_box_spiral },
+    { "center_ptr",		XC_center_ptr },
+    { "circle",			XC_circle },
+    { "clock",			XC_clock },
+    { "coffee_mug",		XC_coffee_mug },
+    { "cross",			XC_cross },
+    { "cross_reverse",		XC_cross_reverse },
+    { "crosshair",		XC_crosshair },
+    { "diamond_cross",		XC_diamond_cross },
+    { "dot",			XC_dot },
+    { "dotbox",			XC_dotbox },
+    { "double_arrow",		XC_double_arrow },
+    { "draft_large",		XC_draft_large },
+    { "draft_small",		XC_draft_small },
+    { "draped_box",		XC_draped_box },
+    { "exchange",		XC_exchange },
+    { "fleur",			XC_fleur },
+    { "gobbler",		XC_gobbler },
+    { "gumby",			XC_gumby },
+    { "hand1",			XC_hand1 },
+    { "hand2",			XC_hand2 },
+    { "heart",			XC_heart },
+    { "icon",			XC_icon },
+    { "iron_cross",		XC_iron_cross },
+    { "left_ptr",		XC_left_ptr },
+    { "left_side",		XC_left_side },
+    { "left_tee",		XC_left_tee },
+    { "leftbutton",		XC_leftbutton },
+    { "ll_angle",		XC_ll_angle },
+    { "lr_angle",		XC_lr_angle },
+    { "man",			XC_man },
+    { "middlebutton",		XC_middlebutton },
+    { "mouse",			XC_mouse },
+    { "pencil",			XC_pencil },
+    { "pirate",			XC_pirate },
+    { "plus",			XC_plus },
+    { "question_arrow",		XC_question_arrow },
+    { "right_ptr",		XC_right_ptr },
+    { "right_side",		XC_right_side },
+    { "right_tee",		XC_right_tee },
+    { "rightbutton",		XC_rightbutton },
+    { "rtl_logo",		XC_rtl_logo },
+    { "sailboat",		XC_sailboat },
+    { "sb_down_arrow",		XC_sb_down_arrow },
+    { "sb_h_double_arrow",	XC_sb_h_double_arrow },
+    { "sb_left_arrow",		XC_sb_left_arrow },
+    { "sb_right_arrow",		XC_sb_right_arrow },
+    { "sb_up_arrow",		XC_sb_up_arrow },
+    { "sb_v_double_arrow",	XC_sb_v_double_arrow },
+    { "shuttle",		XC_shuttle },
+    { "sizing",			XC_sizing },
+    { "spider",			XC_spider },
+    { "spraycan",		XC_spraycan },
+    { "star",			XC_star },
+    { "target",			XC_target },
+    { "tcross",			XC_tcross },
+    { "top_left_arrow",		XC_top_left_arrow },
+    { "top_left_corner",	XC_top_left_corner },
+    { "top_right_corner",	XC_top_right_corner },
+    { "top_side",		XC_top_side },
+    { "top_tee",		XC_top_tee },
+    { "trek",			XC_trek },
+    { "ul_angle",		XC_ul_angle },
+    { "umbrella",		XC_umbrella },
+    { "ur_angle",		XC_ur_angle },
+    { "watch",			XC_watch },
+    { "xterm",			XC_xterm },
+    { NULL,			CURSOR_ID_NONE }
+};
+
+static void check_bitmap_status(int status, char *filename, Pixmap bitmap)
+{
+   switch(status)
+    {
+     case BitmapOpenFailed:
+       wwarning(_("failed to open bitmap file \"%s\""), filename);
+       break;
+     case BitmapFileInvalid:
+       wwarning(_("\"%s\" is not a valid bitmap file"), filename);
+       break;
+     case BitmapNoMemory:
+       wwarning(_("out of memory reading bitmap file \"%s\""), filename);
+       break;
+     case BitmapSuccess:
+       XFreePixmap(dpy, bitmap);
+       break;
+    }
+}
+
+/*
+ * (none)
+ * (builtin, <cursor_name>)
+ * (bitmap, <cursor_bitmap>, <cursor_mask>)
+ */
+static int parse_cursor(WScreen *scr, proplist_t pl, Cursor *cursor)
+{
+   proplist_t elem;
+   char *val;
+   int nelem;
+   int status = 0;
+   
+   nelem = PLGetNumberOfElements(pl);
+   if (nelem < 1)
+    {
+       return(status);
+    }
+   elem = PLGetArrayElement(pl, 0);
+   if (!elem || !PLIsString(elem))
+    {
+       return(status);
+    }
+   val = PLGetString(elem);
+   
+   if (0 == strcasecmp(val, "none")) 
+    {
+       status = 1;
+       *cursor = None;
+    }
+   else if (0 == strcasecmp(val, "builtin")) 
+    {
+       int i;
+       int cursor_id = CURSOR_ID_NONE;
+       
+       if (2 != nelem)
+	{
+	   wwarning(_("bad number of arguments in cursor specification"));
+	   return(status);
+	}
+       elem = PLGetArrayElement(pl, 1);
+       if (!elem || !PLIsString(elem))
+	{
+	   return(status);
+	}
+       val = PLGetString(elem);
+       
+       for (i = 0; NULL != cursor_table[i].name; i++)
+	{
+	   if (0 == strcasecmp(val, cursor_table[i].name))
+	    {
+	       cursor_id = cursor_table[i].id;
+	       break;
+	    }
+	}
+       if (CURSOR_ID_NONE == cursor_id) 
+	{
+	   wwarning(_("unknown builtin cursor name \"%s\""), val);
+	}
+       else
+	{
+	   *cursor = XCreateFontCursor(dpy, cursor_id);
+	   status = 1;
+	}
+    }
+   else if (0 == strcasecmp(val, "bitmap"))
+    {
+       char *bitmap_name;
+       char *mask_name;
+       int bitmap_status;
+       int mask_status;
+       Pixmap bitmap;
+       Pixmap mask;
+       unsigned int w, h;
+       int x, y;
+       XColor fg, bg;
+       
+       if (3 != nelem)
+	{
+	   wwarning(_("bad number of arguments in cursor specification"));
+	   return(status);
+	}
+       elem = PLGetArrayElement(pl, 1);
+       if (!elem || !PLIsString(elem))
+	{
+	   return(status);
+	}
+       val = PLGetString(elem);
+       bitmap_name = FindImage(wPreferences.pixmap_path, val);
+       if (!bitmap_name)
+	{
+	   wwarning(_("could not find cursor bitmap file \"%s\""), val);
+	   return(status);
+	}
+       elem = PLGetArrayElement(pl, 2);
+       if (!elem || !PLIsString(elem))
+	{
+	   free(bitmap_name);
+	   return(status);
+	}
+       val = PLGetString(elem);
+       mask_name = FindImage(wPreferences.pixmap_path, val);
+       if (!mask_name)
+	{
+	   free(bitmap_name);
+	   wwarning(_("could not find cursor bitmap file \"%s\""), val);
+	   return(status);
+	}
+       mask_status = XReadBitmapFile(dpy, scr->w_win, mask_name, &w, &h,
+				     &mask, &x, &y);
+       bitmap_status = XReadBitmapFile(dpy, scr->w_win, bitmap_name, &w, &h,
+				       &bitmap, &x, &y);
+       if ((BitmapSuccess == bitmap_status) &&
+	   (BitmapSuccess == mask_status))
+	{
+	   fg.pixel = scr->black_pixel;
+	   bg.pixel = scr->white_pixel;
+	   XQueryColor(dpy, scr->w_colormap, &fg);
+	   XQueryColor(dpy, scr->w_colormap, &bg);
+	   *cursor = XCreatePixmapCursor(dpy, bitmap, mask, &fg, &bg, x, y);
+	   status = 1;
+	}
+       check_bitmap_status(bitmap_status, bitmap_name, bitmap);
+       check_bitmap_status(mask_status, mask_name, mask);
+       free(bitmap_name);
+       free(mask_name);
+    }
+   return(status);
+}
+
+static int
+getCursor(WScreen *scr, WDefaultEntry *entry, proplist_t value, void *addr,
+	  void **ret)
+{
+   static Cursor cursor;
+   int status;
+   int changed = 0;
+   
+again:
+   if (!PLIsArray(value))
+    {
+       wwarning(_("Wrong option format for key \"%s\". Should be %s."),
+		entry->key, "cursor specification");
+       if (!changed)
+	{
+	   value = entry->plvalue;
+	   changed = 1;
+	   wwarning(_("using default \"%s\" instead"), entry->default_value);
+	   goto again;
+	}
+       return(False);
+    }
+   status = parse_cursor(scr, value, &cursor);
+   if (!status)
+    {
+       wwarning(_("Error in cursor specification for key \"%s\""), entry->key);
+       if (!changed)
+	{
+	   value = entry->plvalue;
+	   changed = 1;
+	   wwarning(_("using default \"%s\" instead"), entry->default_value);
+	   goto again;
+	}
+       return(False);
+    }
+   if (ret)
+    {
+       *ret = &cursor;
+    }
+   if (addr)
+    {
+       *(Cursor *)addr = cursor;
+    }
+   return(True);
+}
+#undef CURSOR_ID_NONE
+
+#endif /* DEFINABLE_CURSOR */
+
 
 /* ---------------- value setting functions --------------- */
 static int
@@ -2871,4 +3191,22 @@
 }
 
 
+#ifdef DEFINABLE_CURSOR
+static int
+setCursor(WScreen *scr, WDefaultEntry *entry, Cursor *cursor, long index)
+{
+   if (None != wCursor[index])
+    {
+       XFreeCursor(dpy, wCursor[index]);
+    }
+   
+   wCursor[index] = *cursor;
+
+   if ((WCUR_ROOT == index) && (None != *cursor))
+    {
+       XDefineCursor(dpy, scr->root_win, *cursor);
+    }
 
+   return 0;
+}
+#endif /* DEFINABLE_CURSOR*/
--- ./src/WindowMaker.h.orig-defcursor	Sun Mar  7 04:55:25 1999
+++ ./src/WindowMaker.h	Wed Mar 24 03:15:10 1999
@@ -120,7 +120,12 @@
 #define WCUR_ARROW	4
 #define WCUR_QUESTION	5
 #define WCUR_TEXT	6
+#ifdef DEFINABLE_CURSOR
+#define WCUR_ROOT	7
+#define WCUR_LAST	8
+#else
 #define WCUR_LAST	7
+#endif
 
 
 /* geometry displays */
--- ./src/startup.c.orig-defcursor	Mon Mar  8 17:10:21 1999
+++ ./src/startup.c	Wed Mar 24 03:29:48 1999
@@ -680,7 +680,12 @@
 
 
     /* cursors */
+#ifdef DEFINABLE_CURSOR
+    wCursor[WCUR_NORMAL] = None;
+    wCursor[WCUR_ROOT] = XCreateFontCursor(dpy, XC_left_ptr);    
+#else
     wCursor[WCUR_NORMAL] = XCreateFontCursor(dpy, XC_left_ptr);    
+#endif
     wCursor[WCUR_ARROW] = XCreateFontCursor(dpy, XC_top_left_arrow);
     wCursor[WCUR_MOVE] = XCreateFontCursor(dpy, XC_fleur);
     wCursor[WCUR_RESIZE] = XCreateFontCursor(dpy, XC_sizing);
