Simplify the option value tokenization by doing it one place
[tig] / tig.c
diff --git a/tig.c b/tig.c
index 0f77167..c270e16 100644 (file)
--- a/tig.c
+++ b/tig.c
 
 #include <curses.h>
 
-static void die(const char *err, ...);
+#if __GNUC__ >= 3
+#define __NORETURN __attribute__((__noreturn__))
+#else
+#define __NORETURN
+#endif
+
+static void __NORETURN die(const char *err, ...);
 static void report(const char *msg, ...);
 static int read_properties(FILE *pipe, const char *separators, int (*read)(char *, int, char *, int));
 static void set_nonblocking_input(bool loading);
@@ -418,7 +424,7 @@ parse_options(int argc, char *argv[])
                if (opt[0] && opt[0] != '-')
                        break;
 
-               die("unknown command '%s'", opt);
+               die("unknown option '%s'\n\n%s", opt, usage);
        }
 
        if (!isatty(STDIN_FILENO)) {
@@ -611,8 +617,8 @@ static struct int_map color_map[] = {
        COLOR_MAP(YELLOW),
 };
 
-#define set_color(color, name, namelen) \
-       set_from_int_map(color_map, ARRAY_SIZE(color_map), color, name, namelen)
+#define set_color(color, name) \
+       set_from_int_map(color_map, ARRAY_SIZE(color_map), color, name, strlen(name))
 
 static struct int_map attr_map[] = {
 #define ATTR_MAP(name) { #name, STRING_SIZE(#name), A_##name }
@@ -625,52 +631,75 @@ static struct int_map attr_map[] = {
        ATTR_MAP(UNDERLINE),
 };
 
-#define set_attribute(attr, name, namelen) \
-       set_from_int_map(attr_map, ARRAY_SIZE(attr_map), attr, name, namelen)
+#define set_attribute(attr, name) \
+       set_from_int_map(attr_map, ARRAY_SIZE(attr_map), attr, name, strlen(name))
 
 static int   config_lineno;
 static bool  config_errors;
 static char *config_msg;
 
+/* Reads
+ *
+ *     object fgcolor bgcolor [attr]
+ *
+ * from the value string. */
 static int
-set_option(char *opt, int optlen, char *value, int valuelen)
+set_option_color(int argc, char *argv[])
 {
-       /* Reads: "color" object fgcolor bgcolor [attr] */
-       if (!strcmp(opt, "color")) {
-               struct line_info *info;
-
-               value = chomp_string(value);
-               valuelen = strcspn(value, " \t");
-               info = get_line_info(value, valuelen);
-               if (!info) {
-                       config_msg = "Unknown color name";
-                       return ERR;
-               }
+       struct line_info *info;
 
-               value = chomp_string(value + valuelen);
-               valuelen = strcspn(value, " \t");
-               if (set_color(&info->fg, value, valuelen) == ERR) {
-                       config_msg = "Unknown color";
-                       return ERR;
-               }
+       if (argc != 3 && argc != 4) {
+               config_msg = "Wrong number of arguments given to color command";
+               return ERR;
+       }
 
-               value = chomp_string(value + valuelen);
-               valuelen = strcspn(value, " \t");
-               if (set_color(&info->bg, value, valuelen) == ERR) {
-                       config_msg = "Unknown color";
-                       return ERR;
-               }
+       info = get_line_info(argv[0], strlen(argv[0]));
+       if (!info) {
+               config_msg = "Unknown color name";
+               return ERR;
+       }
 
-               value = chomp_string(value + valuelen);
-               if (*value &&
-                   set_attribute(&info->attr, value, strlen(value)) == ERR) {
-                       config_msg = "Unknown attribute";
-                       return ERR;
-               }
+       if (set_color(&info->fg, argv[1]) == ERR) {
+               config_msg = "Unknown color";
+               return ERR;
+       }
 
-               return OK;
+       if (set_color(&info->bg, argv[2]) == ERR) {
+               config_msg = "Unknown color";
+               return ERR;
        }
 
+       if (argc == 4 && set_attribute(&info->attr, argv[3]) == ERR) {
+               config_msg = "Unknown attribute";
+               return ERR;
+       }
+
+       return OK;
+}
+
+static int
+set_option(char *opt, char *value)
+{
+       char *argv[16];
+       int valuelen;
+       int argc = 0;
+
+       /* Tokenize */
+       while (argc < ARRAY_SIZE(argv) && (valuelen = strcspn(value, " \t"))) {
+               argv[argc++] = value;
+
+               value += valuelen;
+               if (!*value)
+                       break;
+
+               *value++ = 0;
+               while (isspace(*value))
+                       value++;
+       }
+
+       if (!strcmp(opt, "color"))
+               return set_option_color(argc, argv);
+
        return ERR;
 }
 
@@ -696,7 +725,7 @@ read_option(char *opt, int optlen, char *value, int valuelen)
                value[valuelen] = 0;
        }
 
-       if (set_option(opt, optlen, value, valuelen) == ERR) {
+       if (set_option(opt, value) == ERR) {
                fprintf(stderr, "Error on line %d, near '%.*s' option: %s\n",
                        config_lineno, optlen, opt, config_msg);
                config_errors = TRUE;
@@ -867,8 +896,9 @@ update_view_title(struct view *view)
                wprintw(view->title, "[%s]", view->name);
 
        if (view->lines || view->pipe) {
+               unsigned int view_lines = view->offset + view->height;
                unsigned int lines = view->lines
-                                  ? (view->lineno + 1) * 100 / view->lines
+                                  ? MIN(view_lines, view->lines) * 100 / view->lines
                                   : 0;
 
                wprintw(view->title, " - %s %d of %d (%d%%)",
@@ -2549,12 +2579,6 @@ read_properties(FILE *pipe, const char *separators,
  * Main
  */
 
-#if __GNUC__ >= 3
-#define __NORETURN __attribute__((__noreturn__))
-#else
-#define __NORETURN
-#endif
-
 static void __NORETURN
 quit(int sig)
 {