--- glslideshow.c.orig	2017-03-28 19:49:15.730481140 -0500
+++ glslideshow.c	2019-02-05 19:46:33.523515355 -0600
@@ -73,7 +73,8 @@
                   "*showFPS:         False                \n" \
 	          "*fpsSolid:        True                 \n" \
 	          "*useSHM:          True                 \n" \
-            "*titleFont: -*-helvetica-medium-r-normal-*-*-180-*-*-*-*-*-*\n" \
+            "*titleFont: -*-ubuntu-medium-r-normal-*-*-240-*-*-*-*-*-*\n" \
+            "*commentFont: -*-ubuntu-medium-r-normal-*-*-240-*-*-*-*-*-*\n" \
                   "*desktopGrabber:  xscreensaver-getimage -no-desktop %s\n" \
 		  "*grabDesktopImages:   False \n" \
 		  "*chooseRandomImages:  True  \n"
@@ -94,12 +95,20 @@
 # define DEF_ZOOM           "75"
 # define DEF_FPS_CUTOFF     "5"
 # define DEF_TITLES         "False"
+# define DEF_COMMENTS       "True"
 # define DEF_LETTERBOX      "True"
 # define DEF_DEBUG          "False"
 # define DEF_MIPMAP         "True"
 
+# define COMMENT_INITIAL_Y_OFFSET 50
+# define COMMENT_LINE_Y_OFFSET 35
+
+#define TEXT_OPACITY 0.6
+
 #include "grab-ximage.h"
 #include "texfont.h"
+#include <stdio.h>
+#include <string.h>
 
 typedef struct {
   double x, y, w, h;
@@ -109,6 +118,7 @@
   ModeInfo *mi;
   int id;			   /* unique number for debugging */
   char *title;			   /* the filename of this image */
+  char *comment;       /* the comment for this image */
   int w, h;			   /* size in pixels of the image */
   int tw, th;			   /* size in pixels of the texture */
   XRectangle geom;		   /* where in the image the bits are */
@@ -160,7 +170,8 @@
   Bool checked_fps_p;		/* Whether we have checked for a low
                                    frame rate. */
 
-  texture_font_data *font_data;	/* for printing image file names */
+  texture_font_data *font_data_title;	/* for printing image file names */
+  texture_font_data *font_data_comment;	/* for printing image comments */
 
   int sprite_id, image_id;      /* debugging id counters */
 
@@ -190,6 +201,7 @@
                              */
 static Bool mipmap_p;	    /* Use mipmaps instead of single textures. */
 static Bool do_titles;	    /* Display image titles. */
+static Bool do_comments;	/* Display image comments. */
 static Bool debug_p;	    /* Be loud and do weird things. */
 
 
@@ -200,6 +212,7 @@
   {"-zoom",         ".zoom",          XrmoptionSepArg, 0      },
   {"-cutoff",       ".FPScutoff",     XrmoptionSepArg, 0      },
   {"-titles",       ".titles",        XrmoptionNoArg, "True"  },
+  {"-comments",     ".comments",      XrmoptionNoArg, "True"  },
   {"-letterbox",    ".letterbox",     XrmoptionNoArg, "True"  },
   {"-no-letterbox", ".letterbox",     XrmoptionNoArg, "False" },
   {"-clip",         ".letterbox",     XrmoptionNoArg, "False" },
@@ -218,6 +231,7 @@
   { &fps_cutoff,    "FPScutoff",    "FPSCutoff",    DEF_FPS_CUTOFF,     t_Int},
   { &debug_p,       "debug",        "Debug",        DEF_DEBUG,         t_Bool},
   { &do_titles,     "titles",       "Titles",       DEF_TITLES,        t_Bool},
+  { &do_comments,   "comments",     "Comments",     DEF_COMMENTS,      t_Bool},
 };
 
 ENTRYPOINT ModeSpecOpt slideshow_opts = {countof(opts), opts, countof(vars), vars, NULL};
@@ -298,6 +312,110 @@
   return img;
 }
 
+/* Gets the EXIF comment from a file. Returns NULL if can't find it. */
+static char*
+get_comment_from_file (const char *filename)
+{
+    char line_buffer[16384];
+    FILE* exif_output;
+    char* command_line;
+    char* comment = NULL;
+    if (debug_p)
+      fprintf(stderr, "about to look for comment, filename is %s\n", filename);
+    command_line = (char*) malloc(sizeof(char) * (sizeof("exiftool -UserComment \"") + strlen(filename) + strlen("\" 2> /dev/null") + 1));
+    if (debug_p)
+      fprintf(stderr, "looking for comment\n");
+    memset(line_buffer, 0, sizeof(line_buffer)/sizeof(char));
+    strcpy(command_line, "exiftool -UserComment \"");
+    strcat(command_line, filename);
+    strcat(command_line, "\" 2> /dev/null");
+    if (debug_p)
+      fprintf(stderr, "exiftool command line: %s\n", command_line);
+    exif_output = popen(command_line, "r");
+    while (fgets(line_buffer, sizeof(line_buffer)/sizeof(char), exif_output) != NULL)
+    {
+      /* Make sure the line begins with spaces and "User Comment " */
+      int i = 0;
+      int line_buffer_length = strlen(line_buffer);
+      int begin_pos = -1;
+      while (i < line_buffer_length)
+      {
+        if (line_buffer[i] == 'U')
+        {
+          if (strncmp(&line_buffer[i], "User Comment ", strlen("User Comment ")) == 0)
+          {
+            /* Found it! */
+            /* Skip past the colon */
+            begin_pos = i + strlen("User Comment ");
+            while (begin_pos < sizeof(line_buffer)/sizeof(char) && line_buffer[begin_pos] != ':')
+            {
+              ++begin_pos;
+            }
+            if (begin_pos >= sizeof(line_buffer)/sizeof(char) - 2)
+            {
+              comment = malloc(10);
+              comment[0] = '~';
+              comment[1] = '!';
+              comment[2] = '\0';
+              begin_pos = -1;
+            }
+            else
+            {
+              ++begin_pos;
+              ++begin_pos;
+            }
+            /* Either way, we can stop. */
+            break;
+          }
+        }
+        ++i;
+      }
+      if (begin_pos != -1)
+      {
+        comment = (char*)malloc(sizeof(char) * (strlen(&line_buffer[begin_pos]) + 1));
+        strcpy(comment, &line_buffer[begin_pos]);
+        /* For testing line wrapping
+        comment = (char*)malloc(sizeof(char) * (strlen(&line_buffer[begin_pos]) * 3 + 1));
+        strcpy(comment, &line_buffer[begin_pos]);
+        strcpy(&comment[strlen(&line_buffer[begin_pos]) - 1], &line_buffer[begin_pos]);
+        strcpy(&comment[strlen(&line_buffer[begin_pos]) * 2 - 2], &line_buffer[begin_pos]);
+        */
+        pclose(exif_output);
+        free(command_line);
+        break;
+      }
+    }
+    return comment;
+}
+
+/* Gets the EXIF comment from a file. Returns NULL if can't find it. */
+static char*
+get_comment_from_filename_prefix (const char *filename_without_extension)
+{
+    /* TODO - sigh, don't know how to get this from the fn params */
+    const char* prefix = "/home/gregstoll/images/allgallerypictures/";
+    size_t full_name_size = sizeof(char) * (strlen(prefix) + strlen(filename_without_extension) + sizeof(".jpg") + 1);
+    char* full_name = (char*) calloc(1, full_name_size);
+    char* comment;
+    /* TODO - this is terrible.  Somewhere along the way the extension
+     * gets stripped out (see get_name_from_xprops, I think?) */
+    strcpy(full_name, prefix);
+    strcat(full_name, filename_without_extension);
+    strcat(full_name, ".jpg");
+    comment = get_comment_from_file(full_name);
+    if (comment != NULL)
+    {
+        free(full_name);
+        return comment;
+    }
+    memset(full_name, 0, full_name_size);
+    strcpy(full_name, prefix);
+    strcat(full_name, filename_without_extension);
+    strcat(full_name, ".JPG");
+    comment = get_comment_from_file(full_name);
+    free(full_name);
+    return comment;
+}
 
 /* Callback that tells us that the texture has been loaded.
  */
@@ -338,6 +456,11 @@
   img->th = texture_height;
   img->geom = *geom;
   img->title = (filename ? strdup (filename) : 0);
+  /* Only load the comment if requested, since it adds a little overhead. */
+  if (do_comments)
+  {
+    img->comment = get_comment_from_filename_prefix(filename);
+  } 
 
   /* If the image's width doesn't come back as the width of the screen,
      then the image must have been scaled down (due to insufficient
@@ -413,6 +536,7 @@
              blurb(), img->id, (img->title ? img->title : "(null)"));
 
   if (img->title) free (img->title);
+  if (img->comment) free (img->comment);
   glDeleteTextures (1, &img->texid);
   free (img);
 }
@@ -809,11 +933,76 @@
         img->title && *img->title &&
         (sp->state == IN || sp->state == FULL))
       {
-        glColor4f (1, 1, 1, sp->opacity);
-        print_texture_label (mi->dpy, ss->font_data,
+        glColor4f (1, 1, 1, TEXT_OPACITY);
+        print_texture_label (mi->dpy, ss->font_data_title,
                              mi->xgwa.width, mi->xgwa.height,
                              1, img->title);
       }
+
+    if (do_comments &&
+        img->comment && *img->comment &&
+        (sp->state == IN || sp->state == FULL))
+    {
+      /* Break up comment by line */
+      /* It would be nice if we could measure the font and tell exactly
+       * how big it's going to be - maybe we could use string_to_texture()? */
+      int y = COMMENT_INITIAL_Y_OFFSET;
+      char temp_char = '\0';
+      int comment_pos = 0;
+      /* See where we have to break the line. */
+      while(comment_pos < strlen(img->comment))
+      {
+        int where_to_break, orig_where_to_break, len;
+        
+        where_to_break = mi->xgwa.width / 16; /* 12; */
+        len = strlen(&img->comment[comment_pos]);
+        if (where_to_break > len)
+        {
+          if (len > 0 && img->comment[comment_pos+len-1] == '\n')
+          {
+            img->comment[comment_pos+len-1] = '\0';
+          }
+          /* No need to break. */
+        }
+        else
+        {
+          /* Find a friendly spot to break, if possible. */
+          orig_where_to_break = where_to_break;
+          where_to_break = comment_pos + orig_where_to_break;
+          while (img->comment[where_to_break] != ' ' && img->comment[where_to_break] != '\t' && img->comment[where_to_break] != '\n' && where_to_break > comment_pos)
+          {
+            --where_to_break;
+          }
+          /* If we found nothing, too bad. */
+          if (where_to_break == comment_pos)
+          {
+            where_to_break = comment_pos + orig_where_to_break;
+          }
+          temp_char = img->comment[where_to_break];
+          img->comment[where_to_break] = '\0';
+          }
+        glColor4f (1, 1, 1, TEXT_OPACITY);
+        print_texture_label_with_offset (mi->dpy, ss->font_data_comment,
+                             mi->xgwa.width, mi->xgwa.height,
+                             1, &img->comment[comment_pos],
+                             0, -1 * y);
+
+        if (temp_char != '\0')
+        {
+          img->comment[where_to_break] = temp_char;
+          comment_pos = where_to_break + 1;
+          if (temp_char != ' ' && temp_char != '\t' && temp_char != '\n')
+          {
+            --comment_pos;
+          }
+          temp_char = '\0';
+          y += COMMENT_LINE_Y_OFFSET;
+        } else {
+          comment_pos = strlen(img->comment);
+        }
+      }
+    }
+
   }
   glPopMatrix();
 
@@ -1118,7 +1307,8 @@
 
   if (debug_p) glLineWidth (3);
 
-  ss->font_data = load_texture_font (mi->dpy, "titleFont");
+  ss->font_data_title = load_texture_font (mi->dpy, "titleFont");
+  ss->font_data_comment = load_texture_font (mi->dpy, "commentFont");
 
   if (debug_p)
     hack_resources();
