WolframAutomata now uses a black background for the pixmap, reserving the fg/bg color...
[screensavers] / hacks / WolframAutomata / WolframAutomata.c
index faab86b..b6da506 100644 (file)
 /* TODO: I suppose a lot of this stuff goes in the README instead. */
 /* TODO: Explain the data structures in detail. */
 /* TODO: Explain all the options, like the various starting conditions. */
 /* TODO: I suppose a lot of this stuff goes in the README instead. */
 /* TODO: Explain the data structures in detail. */
 /* TODO: Explain all the options, like the various starting conditions. */
+/* TODO: Explain all the dependencies like libXpm. */
 
 
 
 
+/* TODO: Add a #define for the hack version. */
 /* TODO: Check manpage for all functions I use and ensure my includes are correct. I don't want to depend on picking up includes via screenhack.h. */
 /* TODO: Verify everything in this file is C89. Get rid of things like '//' comments, pack all my declarations upfront, no stdint, etc. */
 
 /* TODO: Check manpage for all functions I use and ensure my includes are correct. I don't want to depend on picking up includes via screenhack.h. */
 /* TODO: Verify everything in this file is C89. Get rid of things like '//' comments, pack all my declarations upfront, no stdint, etc. */
 
 // Command line options
 //        directory to output XBM files of each run (and call an external command to convert to PNGs?)
 //              -save-dir STRING
 // Command line options
 //        directory to output XBM files of each run (and call an external command to convert to PNGs?)
 //              -save-dir STRING
+//              (could use libXpm to save an XPM and then convert to PNG with ImageMagick) (this is a single function call to go from pixmap -> file)
+//              (since it depends on an external library, make this whole feature optional at build-time?)
 //        number of generations to simulate
 //        number of generations to simulate
+//              -random-generations
 //              -num-generations N
 //        delay time (speed of simulation)
 //              -num-generations N
 //        delay time (speed of simulation)
+//              -random-delay
 //              -delay-usec N
 //        foreground and background color
 //              -random-colors (highest precedence)
 //              -delay-usec N
 //        foreground and background color
 //              -random-colors (highest precedence)
@@ -43,6 +49,7 @@
 //              -background "COLORNAME"
 //              (default is black and white)
 //              (mention sample color combinations in manpage, and link to: https://en.wikipedia.org/wiki/X11_color_names)
 //              -background "COLORNAME"
 //              (default is black and white)
 //              (mention sample color combinations in manpage, and link to: https://en.wikipedia.org/wiki/X11_color_names)
+//              (note to the user that most color names they can naturally think of (e.g. red, purple, gray, pink, etc) are valid X11 color names for these CLI options.)
 //        display info overlay with CA number and start conditions?
 //              -overlay
 //        which ruleset number to use? Or random? Or random from small set of hand-selected interesting examples?
 //        display info overlay with CA number and start conditions?
 //              -overlay
 //        which ruleset number to use? Or random? Or random from small set of hand-selected interesting examples?
@@ -57,6 +64,7 @@
 //                  (the two options above only apply to the simulation under the -rule-random or -rule N options. in curated mode, starting population is defined in the curation array)
 //                  TODO: In the future, add the option for user to pass list of cell IDs to turn ON.
 //        size of pixel square (e.g. 1x1, 2x2, 3x3, etc)
 //                  (the two options above only apply to the simulation under the -rule-random or -rule N options. in curated mode, starting population is defined in the curation array)
 //                  TODO: In the future, add the option for user to pass list of cell IDs to turn ON.
 //        size of pixel square (e.g. 1x1, 2x2, 3x3, etc)
+//              -random-pixel-size
 //              -pixel-size N
 
 /* -------------------------------------------------------------------------- */
 //              -pixel-size N
 
 /* -------------------------------------------------------------------------- */
@@ -159,9 +167,35 @@ struct color_pair {
 };
 
 // TODO: Decorations
 };
 
 // TODO: Decorations
-// TODO: Populate this table with more examples.
 static const struct color_pair color_list[] = {
 static const struct color_pair color_list[] = {
+    {"red", "black"},
+    {"olive", "black"},
+    {"teal", "black"},
+    {"slateblue", "black"},
+    {"violet", "black"},
+    {"purple", "black"},
     {"white", "black"},
     {"white", "black"},
+    {"white", "darkgreen"},
+    {"white", "darkmagenta"},
+    {"white", "darkred"},
+    {"white", "darkblue"},
+    {"darkslategray", "darkslategray1"},
+    {"lightsteelblue", "darkslategray"},
+    {"royalblue4", "royalblue"},
+    {"antiquewhite2", "antiquewhite4"},
+    {"darkolivegreen1", "darkolivegreen"},
+    {"darkseagreen1", "darkseagreen4"},
+    {"pink", "darkred"},
+    {"lightblue", "darkgreen"},
+    {"red", "blue"},
+    {"red", "darkgreen"},
+    {"aqua", "teal"},
+    {"darkblue", "teal"},
+    {"khaki", "seagreen"},
+    {"khaki", "darkolivegreen"},
+    {"lightslategray", "darkslategray"},
+    {"tomato", "darkslategray"},
+    {"tomato", "darkcyan"}
 };
 
 /* -------------------------------------------------------------------------- */
 };
 
 /* -------------------------------------------------------------------------- */
@@ -220,6 +254,10 @@ render_current_generation(struct state * state)
     for (xpos = 0; xpos < state->number_of_cells; xpos++) {
         if (state->current_generation[xpos] == True) {
             XFillRectangle(state->dpy, state->evolution_history, state->gc, xpos*state->pixel_size, state->ypos, state->pixel_size, state->pixel_size);
     for (xpos = 0; xpos < state->number_of_cells; xpos++) {
         if (state->current_generation[xpos] == True) {
             XFillRectangle(state->dpy, state->evolution_history, state->gc, xpos*state->pixel_size, state->ypos, state->pixel_size, state->pixel_size);
+        } else {
+            XSetForeground(state->dpy, state->gc, state->bg);
+            XFillRectangle(state->dpy, state->evolution_history, state->gc, xpos*state->pixel_size, state->ypos, state->pixel_size, state->pixel_size);
+            XSetForeground(state->dpy, state->gc, state->fg);
         }
     }
 }
         }
     }
 }
@@ -231,7 +269,12 @@ render_current_generation(struct state * state)
 static void *
 WolframAutomata_init(Display * dpy, Window win)
 {
 static void *
 WolframAutomata_init(Display * dpy, Window win)
 {
-    struct state * state = calloc(1, sizeof(*state)); // TODO: Check calloc() call
+    struct state * state = calloc(1, sizeof(*state));
+    if (!state) {
+        fprintf(stderr, "ERROR: Failed to calloc() for state struct in WolframAutomata_init().\n");
+        exit(EXIT_FAILURE);
+    }
+
     XGCValues gcv;
     XWindowAttributes xgwa;
     const struct curated_ruleset * curated_ruleset = NULL;
     XGCValues gcv;
     XWindowAttributes xgwa;
     const struct curated_ruleset * curated_ruleset = NULL;
@@ -302,7 +345,7 @@ WolframAutomata_init(Display * dpy, Window win)
     if (state->population_density < 0 || state->population_density > 100) state->population_density = 50;
     state->current_generation = calloc(1, sizeof(*state->current_generation)*state->number_of_cells);
     if (!state->current_generation) {
     if (state->population_density < 0 || state->population_density > 100) state->population_density = 50;
     state->current_generation = calloc(1, sizeof(*state->current_generation)*state->number_of_cells);
     if (!state->current_generation) {
-        fprintf(stderr, "ERROR: Failed to calloc() in WolframAutomata_init().\n");
+        fprintf(stderr, "ERROR: Failed to calloc() for cell generation in WolframAutomata_init().\n");
         exit(EXIT_FAILURE);
     }
     if (curated_ruleset) {
         exit(EXIT_FAILURE);
     }
     if (curated_ruleset) {
@@ -331,7 +374,9 @@ WolframAutomata_init(Display * dpy, Window win)
     state->evolution_history = XCreatePixmap(state->dpy, state->win, state->xlim, state->num_generations*state->pixel_size, xgwa.depth);
     // Pixmap contents are undefined after creation. Explicitly set a black
     // background by drawing a black rectangle over the entire pixmap.
     state->evolution_history = XCreatePixmap(state->dpy, state->win, state->xlim, state->num_generations*state->pixel_size, xgwa.depth);
     // Pixmap contents are undefined after creation. Explicitly set a black
     // background by drawing a black rectangle over the entire pixmap.
-    XSetForeground(state->dpy, state->gc, state->bg);
+    XColor blackx, blacks;
+    XAllocNamedColor(state->dpy, DefaultColormapOfScreen(DefaultScreenOfDisplay(state->dpy)), "black", &blacks, &blackx);
+    XSetForeground(state->dpy, state->gc, blacks.pixel);
     XFillRectangle(state->dpy, state->evolution_history, state->gc, 0, 0, state->xlim, state->num_generations*state->pixel_size);
     XSetForeground(state->dpy, state->gc, state->fg);
     render_current_generation(state);
     XFillRectangle(state->dpy, state->evolution_history, state->gc, 0, 0, state->xlim, state->num_generations*state->pixel_size);
     XSetForeground(state->dpy, state->gc, state->fg);
     render_current_generation(state);