Browse Source

Work on status: Add \s[]\ \r[]\ sequences for text & rectangle

Martin Duquesnoy 12 years ago
parent
commit
f6c0bc8a6c
4 changed files with 231 additions and 9 deletions
  1. 202 7
      src/status.c
  2. 2 2
      src/util.c
  3. 15 0
      src/util.h
  4. 12 0
      src/wmfs.h

+ 202 - 7
src/status.c

@@ -8,21 +8,216 @@
 #include "infobar.h"
 #include "util.h"
 
+#include <string.h>
+
+/* Parse arg;between;semicolon */
+#define STATUS_GET_ARGS(i, inc, p, arg, n)                                \
+     do {                                                                 \
+          for(i = 0, p += inc, arg[0] = p; *p && *p != ']' && i < n; ++p) \
+               if(*p == ';')                                              \
+               {                                                          \
+                    *p = '\0';                                            \
+                    arg[++i] = ++p;                                       \
+               }                                                          \
+          *p = '\0';                                                      \
+     } while(/* CONSTCOND */ 0);
+
+#define STATUS_CHECK_END(str, end, p)           \
+     if(!(end = strstr(p, "]\\")))              \
+     {                                          \
+          str = end + 2;                        \
+          continue;                             \
+     }
+
+#define STATUS_CHECK_ARGS(i, n1, n2, str, end)  \
+     if(i != n1 && i != n2)                     \
+     {                                          \
+          str = end + 2;                        \
+          continue;                             \
+     }
+
+/* Alloc & fill status_sq struct with universal options: align/position and type */
+#define STATUS_FILL_SQ(sq, t, shift, arg)                               \
+     do {                                                               \
+          sq = xcalloc(1, sizeof(struct status_seq));                   \
+          sq->type = t;                                                 \
+                                                                        \
+          if(!strcmp(arg[0], "right") || !strcmp(arg[0], "left"))       \
+               sq->align = str_to_position(arg[0]);                     \
+          else                                                          \
+          {                                                             \
+               sq->align = NoAlign;                                     \
+               sq->geo.x = ATOI(arg[0]);                                \
+               sq->geo.y = ATOI(arg[1]);                                \
+               shift = 1;                                               \
+          }                                                             \
+     } while(/* CONSTCOND */ 0);                                        \
+
+
+/** Check text blocks in str and list it
+ * --> \s[left/right;#color;text]\ OR \s[x;y;#color;text]\
+ *\param ib Infobar pointer
+ *\param str String
+ */
+static void
+status_text(struct infobar *ib, char *str)
+{
+     struct status_seq *sq;
+     int i;
+     char *dstr = xstrdup(str), *sauv = dstr;
+     char *p, *end;
+
+     while((p = strstr(dstr, "\\s[")))
+     {
+          char *arg[5] = { NULL };
+          int shift = 0;
+
+          STATUS_CHECK_END(dstr, end, p);
+          STATUS_GET_ARGS(i, 3, p, arg, 4);
+          STATUS_CHECK_ARGS(i, 2, 3, dstr, end);
+          STATUS_FILL_SQ(sq, 's', shift, arg);
+
+          /* string sequence options */
+          sq->color = color_atoh(arg[1 + shift]);
+          sq->str = xstrdup(arg[2 + shift]);
+
+          SLIST_INSERT_HEAD(&ib->statushead, sq, next);
+
+          dstr = end + 2;
+     }
+
+     free(sauv);
+}
+
+/** Check rectangle blocks in str and list it
+ * --> \s[left/right;width;height;#color]\ OR \s[x;y;width;height;#color]\
+ *\param ib Infobar pointer
+ *\param str String
+ */
+static void
+status_rect(struct infobar *ib, char *str)
+{
+     struct status_seq *sq;
+     int i;
+     char *dstr = xstrdup(str), *sauv = dstr;
+     char *p, *end;
+
+     while((p = strstr(dstr, "\r[")))
+     {
+          char *arg[6] = { NULL };
+          int shift = 0;
+
+          STATUS_CHECK_END(dstr, end, p);
+          STATUS_GET_ARGS(i, 2, p, arg, 5);
+          STATUS_CHECK_ARGS(i, 3, 4, dstr, end);
+          STATUS_FILL_SQ(sq, 'r', shift, arg);
+
+          /* rectangle sequence options */
+          sq->geo.w = ATOI(arg[1 + shift]);
+          sq->geo.h = ATOI(arg[2 + shift]);
+          sq->color = color_atoh(arg[3 + shift]);
+
+          SLIST_INSERT_HEAD(&ib->statushead, sq, next);
+
+          dstr = end + 2;
+     }
+
+     free(sauv);
+}
+
+static void
+status_apply_list(struct element *e)
+{
+     struct status_seq *sq;
+     struct barwin *b = SLIST_FIRST(&e->bars);
+     int left = 0, right = 0;
+     int l;
+
+     SLIST_FOREACH(sq, &e->infobar->statushead, next)
+     {
+          switch(sq->type)
+          {
+          /* Text */
+          case 's':
+               if(sq->align == NoAlign)
+                    draw_text(b->dr, e->infobar->theme, sq->geo.x, sq->geo.y, sq->color, sq->str);
+               else if(sq->align == Left)
+               {
+                    draw_text(b->dr, e->infobar->theme, left, TEXTY(e->infobar->theme, e->geo.h), sq->color, sq->str);
+                    left += draw_textw(e->infobar->theme, sq->str);
+               }
+               else if(sq->align == Right)
+               {
+                    l = draw_textw(e->infobar->theme, sq->str);
+                    draw_text(b->dr, e->infobar->theme, e->geo.w - right - l,
+                              TEXTY(e->infobar->theme, e->geo.h), sq->color, sq->str);
+                    right += l;
+               }
+               break;
+
+          /* Rectangle */
+          case 'r':
+               if(sq->align != NoAlign)
+                    sq->geo.y = (e->geo.h >> 1) - (sq->geo.h >> 1);
+
+               if(sq->align == Left)
+               {
+                    sq->geo.x = left;
+                    left += sq->geo.w;
+               }
+               else if(sq->align == Right)
+               {
+                    sq->geo.x = e->geo.w - right - sq->geo.w;
+                    right += sq->geo.w;
+               }
+
+               draw_rect(b->dr, sq->geo, sq->color);
+               break;
+          }
+     }
+}
+
 void
 status_manage(struct element *e)
 {
+     struct status_seq *sq;
      struct barwin *b = SLIST_FIRST(&e->bars);
-     int l;
 
-     barwin_refresh_color(b);
+     SLIST_INIT(&e->infobar->statushead);
 
-     if(e->infobar->status)
+     /* Flush previous linked list of status sequences */
+     while(!SLIST_EMPTY(&e->infobar->statushead))
      {
-          l = draw_textw(e->infobar->theme, e->infobar->status);
-          draw_text(b->dr, e->infobar->theme, e->geo.w - l,
-                    TEXTY(e->infobar->theme, e->geo.h), b->fg, e->infobar->status);
-          barwin_refresh(b);
+          sq = SLIST_FIRST(&e->infobar->statushead);
+          SLIST_REMOVE_HEAD(&e->infobar->statushead, next);
+          free(sq->str);
+          free(sq);
      }
+
+     if(!e->infobar->status)
+          return;
+
+     barwin_refresh_color(b);
+
+     status_text(e->infobar, e->infobar->status);
+     status_rect(e->infobar, e->infobar->status);
+
+     /* DEBUG
+        SLIST_FOREACH(sq, &e->infobar->statushead, next)
+        printf("-> %c (%d;%d)x(%d;%d) (%d) (#%x) (%s)\n",
+        sq->type, sq->geo.x, sq->geo.y, sq->geo.w, sq->geo.h, sq->align, sq->color, sq->str);
+     */
+
+     status_apply_list(e);
+
+     /*
+       l = draw_textw(e->infobar->theme, e->infobar->status);
+       draw_text(b->dr, e->infobar->theme, e->geo.w - l,
+       TEXTY(e->infobar->theme, e->geo.h), b->fg, e->infobar->status);
+     */
+
+     barwin_refresh(b);
+
 }
 
 /* Syntax: "<infobar name> <status string>" */

+ 2 - 2
src/util.c

@@ -76,8 +76,8 @@ xstrdup(const char *str)
 {
      char *ret;
 
-     if (str == NULL || (ret = strdup(str)) == NULL)
-          err(EXIT_FAILURE, "strdup(%s)", str);
+     if(str == NULL || (ret = strdup(str)) == NULL)
+          warnx("strdup(%s)", str);
 
      return ret;
 }

+ 15 - 0
src/util.h

@@ -8,6 +8,8 @@
 
 #include "wmfs.h"
 
+#include <string.h>
+
 /* Todo FREE_LIST(type, head, function_remove) */
 #define FREE_LIST(type, head)                   \
      do {                                       \
@@ -54,6 +56,19 @@ swap_ptr(void **x, void **y)
      *y = t;
 }
 
+static inline enum position
+str_to_position(char *str)
+{
+     enum position i;
+     static const char index[PositionLast][8] = { "right", "left", "top", "bottom", "center" };
+
+     for(i = 0; i < PositionLast; ++i)
+          if(!strcmp(index[i], str))
+               return i;
+
+     return Right;
+}
+
 void *xmalloc(size_t nmemb, size_t size);
 void *xcalloc(size_t nmemb, size_t size);
 int xasprintf(char **strp, const char *fmt, ...);

+ 12 - 0
src/wmfs.h

@@ -46,6 +46,7 @@ enum position
      Top,
      Bottom,
      Center,
+     NoAlign,
      PositionLast
 };
 
@@ -92,6 +93,16 @@ struct barwin
      SLIST_ENTRY(barwin) enext; /* element barwin */
 };
 
+struct status_seq
+{
+     struct geo geo;
+     enum position align;
+     char type;
+     char *str;
+     Color color;
+     SLIST_ENTRY(status_seq) next;
+};
+
 struct element
 {
      struct geo geo;
@@ -115,6 +126,7 @@ struct infobar
      char *name;
      char *status;
      TAILQ_HEAD(esub, element) elements;
+     SLIST_HEAD(, status_seq) statushead;
      SLIST_ENTRY(infobar) next;
 };