Переглянути джерело

Clean code by adding function instead macros for seq parsing AND allow multi mousebinds sequence: \[](;;)(;;)(;;)

Martin Duquesnoy 12 роки тому
батько
коміт
f46cbaf501
5 змінених файлів з 88 додано та 88 видалено
  1. 2 0
      src/infobar.c
  2. 66 87
      src/status.c
  3. 17 0
      src/util.c
  4. 1 0
      src/util.h
  5. 2 1
      src/wmfs.h

+ 2 - 0
src/infobar.c

@@ -268,6 +268,8 @@ infobar_new(struct screen *s, char *name, struct theme *theme, enum barpos pos,
      /* struct elements */
      infobar_elem_init(i);
 
+     SLIST_INIT(&i->statushead);
+
      /* Render, only if pos is Top or Bottom */
      if(!map)
           return i;

+ 66 - 87
src/status.c

@@ -10,43 +10,28 @@
 #include "util.h"
 
 #include <string.h>
-#include <ctype.h>
-
-/* Parse arg;between;semicolon */
-#define STATUS_GET_ARGS(i,  p, arg, n)                                  \
-     do {                                                               \
-          for(i = 0, p += 2, arg[0] = p; *p && *p != ']' && i < n; ++p) \
-               if(*p == ';')                                            \
-               {                                                        \
-                    *p = '\0';                                          \
-                    arg[++i] = ++p;                                     \
-               }                                                        \
-          *p = '\0';                                                    \
-     } while(/* CONSTCOND */ 0);
 
-#define STATUS_CHECK_ARGS(i, n1, n2, str, end)  \
-     if(i != n1 && i != n2)                     \
-     {                                          \
-          str = end + 2;                        \
-          continue;                             \
+static struct status_seq*
+status_new_seq(char type, int narg, int minarg, char *args[], int *shift)
+{
+     struct status_seq *sq = xcalloc(1, sizeof(struct status_seq));
+
+     SLIST_INIT(&sq->mousebinds);
+     sq->type = type;
+     *shift = 0;
+
+     if(narg == minarg ||  !strcmp(args[0], "right") || !strcmp(args[0], "left"))
+          sq->align = str_to_position(args[0]);
+     else
+     {
+          sq->align = NoAlign;
+          sq->geo.x = ATOI(args[0]);
+          sq->geo.y = ATOI(args[1]);
+          *shift = 1;
      }
 
-/* Alloc & fill status_sq struct with universal options: align/position and type */
-#define STATUS_FILL_SQ(sq, t, ma, shift, arg)                           \
-     do {                                                               \
-          sq = xcalloc(1, sizeof(struct status_seq));                   \
-          sq->type = t;                                                 \
-                                                                        \
-          if(i == ma || !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);                                        \
+     return sq;
+}
 
 /* Parse mousebind sequence next normal sequence: \<seq>[](button;func;cmd) */
 static char*
@@ -54,19 +39,13 @@ status_parse_mouse(struct status_seq *sq, struct element *e, char *str)
 {
      struct mousebind *m;
      struct barwin *b = SLIST_FIRST(&e->bars);
-     char *arg[3] = { NULL };
+     char *end, *arg[3] = { NULL };
      int i;
 
-     if(*str != '(' || !strchr(str, ')'))
+     if(*str != '(' || !(end = strchr(str, ')')))
           return str + 1;
 
-     for(i = 0, ++str, arg[0] = str; *str && *str != ')' && i < 3; ++str)
-          if(*str == ';')
-          {
-               *str = '\0';
-               arg[++i] = ++str;
-          }
-     *str = '\0';
+     i = parse_args(++str, ';', ')', 3, arg);
 
      m = xcalloc(1, sizeof(struct mousebind));
 
@@ -75,13 +54,18 @@ status_parse_mouse(struct status_seq *sq, struct element *e, char *str)
      m->func     = uicb_name_func(arg[1]);
      m->cmd      = (i > 1 ? xstrdup(arg[2]) : NULL);
 
-     sq->mousebind = m;
-
      SLIST_INSERT_HEAD(&b->mousebinds, m, next);
+     SLIST_INSERT_HEAD(&sq->mousebinds, m, snext);
 
-     return str + 1;
+     return end + 1;
 }
 
+#define STATUS_CHECK_ARGS(i, n1, n2, str, end)  \
+     if(i != n1 && i != n2)                     \
+     {                                          \
+          str = end + 2;                        \
+          continue;                             \
+     }
 static void
 status_parse(struct element *e)
 {
@@ -102,15 +86,15 @@ status_parse(struct element *e)
                continue;
 
           /* Then parse & list it */
-          switch((type = tolower(*p)))
+          switch((type = *p) )
           {
           /*
            * Text sequence: \s[left/right;#color;text] OR \s[x;y;#color;text]
            */
           case 's':
-               STATUS_GET_ARGS(i, p, arg, 4);
+               i = parse_args(p + 2,  ';', ']', 4, arg);
                STATUS_CHECK_ARGS(i, 2, 3, dstr, end);
-               STATUS_FILL_SQ(sq, type, 2, shift, arg);
+               sq = status_new_seq(type, i, 2, arg, &shift);
 
                sq->color = color_atoh(arg[1 + shift]);
                sq->str = xstrdup(arg[2 + shift]);
@@ -120,10 +104,10 @@ status_parse(struct element *e)
          /*
           * Rectangle sequence: \R[left/right;w;h;#color] OR \R[x;y;w;h;#color]
           */
-          case 'r':
-               STATUS_GET_ARGS(i, p, arg, 5);
+          case 'R':
+               i = parse_args(p + 2, ';', ']', 5, arg);
                STATUS_CHECK_ARGS(i, 3, 4, dstr, end);
-               STATUS_FILL_SQ(sq, type, 3, shift, arg);
+               sq = status_new_seq(type, i, 3, arg, &shift);
 
                sq->geo.w = ATOI(arg[1 + shift]);
                sq->geo.h = ATOI(arg[2 + shift]);
@@ -134,22 +118,36 @@ status_parse(struct element *e)
 
           SLIST_INSERT_TAIL(&e->infobar->statushead, sq, next, prev);
 
-          dstr = status_parse_mouse(sq, e, end + 1);
-
-          printf(":%s\n", dstr);
+          /*
+           * Optional mousebind sequence(s) \<seq>[](button;func;cmd)
+           * Parse it while there is a mousebind sequence.
+           */
+          dstr = ++end;
+          while((*(dstr = status_parse_mouse(sq, e, dstr)) == '('));
 
-          shift = 0;
           prev = sq;
      }
 
      free(sauv);
 }
 
+#define STATUS_ALIGN(align)                             \
+     if(align == Left)                                  \
+     {                                                  \
+          sq->geo.x = left;                             \
+          left += sq->geo.w;                            \
+     }                                                  \
+     else if(align == Right)                            \
+     {                                                  \
+          sq->geo.x = e->geo.w - right - sq->geo.w;     \
+          right += sq->geo.w;                           \
+     }
 static void
 status_apply_list(struct element *e)
 {
      struct status_seq *sq;
      struct barwin *b = SLIST_FIRST(&e->bars);
+     struct mousebind *m;
      int left = 0, right = 0;
 
      SLIST_FOREACH(sq, &e->infobar->statushead, next)
@@ -164,48 +162,31 @@ status_apply_list(struct element *e)
                if(sq->align != NoAlign)
                     sq->geo.y = TEXTY(e->infobar->theme, e->geo.h);
 
-               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;
-               }
+               STATUS_ALIGN(sq->align);
 
                draw_text(b->dr, e->infobar->theme, sq->geo.x, sq->geo.y, sq->color, sq->str);
 
-               if(sq->mousebind)
-               {
-                    sq->mousebind->area = sq->geo;
-                    sq->mousebind->area.y -= sq->geo.h;
-               }
+               if(!SLIST_EMPTY(&sq->mousebinds))
+                    SLIST_FOREACH(m, &sq->mousebinds, snext)
+                    {
+                         m->area = sq->geo;
+                         m->area.y -= sq->geo.h;
+                    }
 
                break;
 
           /* Rectangle */
-          case 'r':
+          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;
-               }
-
+               STATUS_ALIGN(sq->align);
 
                draw_rect(b->dr, sq->geo, sq->color);
 
-               if(sq->mousebind)
-                    sq->mousebind->area = sq->geo;
+               if(!SLIST_EMPTY(&sq->mousebinds))
+                    SLIST_FOREACH(m, &sq->mousebinds, snext)
+                         m->area = sq->geo;
 
                break;
           }
@@ -244,8 +225,6 @@ status_manage(struct element *e)
      struct mousebind *m;
      struct barwin *b = SLIST_FIRST(&e->bars);
 
-     SLIST_INIT(&e->infobar->statushead);
-
      /*
       * Flush previous linked list of status sequences
       * and mousebind of status barwin

+ 17 - 0
src/util.c

@@ -121,6 +121,23 @@ spawn(const char *format, ...)
      return pid;
 }
 
+int
+parse_args(char *str, char delim, char end, int narg, char *args[])
+{
+     int i = 0;
+
+     for(args[0] = str; *str && *str != end && i < narg; ++str)
+          if(*str == delim)
+          {
+               *str = '\0';
+               args[++i] = ++str;
+          }
+
+     *str = '\0';
+
+     return i;
+}
+
 void
 uicb_spawn(Uicb cmd)
 {

+ 1 - 0
src/util.h

@@ -81,6 +81,7 @@ void *xcalloc(size_t nmemb, size_t size);
 int xasprintf(char **strp, const char *fmt, ...);
 char *xstrdup(const char *str);
 pid_t spawn(const char *format, ...);
+int parse_args(char *str, char delim, char end, int narg, char *args[]);
 void uicb_spawn(Uicb cmd);
 
 #endif /* UTIL_H */

+ 2 - 1
src/wmfs.h

@@ -96,11 +96,11 @@ struct barwin
 struct status_seq
 {
      struct geo geo;
-     struct mousebind *mousebind;
      enum position align;
      char type;
      char *str;
      Color color;
+     SLIST_HEAD(, mousebind) mousebinds;
      SLIST_ENTRY(status_seq) next;
 };
 
@@ -212,6 +212,7 @@ struct mousebind
      void (*func)(Uicb);
      Uicb cmd;
      SLIST_ENTRY(mousebind) next;
+     SLIST_ENTRY(mousebind) snext;
 };
 
 struct theme