+/*
+ * Line-oriented content detection.
+ */
+
+#define LINE_INFO \
+LINE(DIFF_HEADER, "diff --git ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DIFF_CHUNK, "@@", COLOR_MAGENTA, COLOR_DEFAULT, 0), \
+LINE(DIFF_ADD, "+", COLOR_GREEN, COLOR_DEFAULT, 0), \
+LINE(DIFF_DEL, "-", COLOR_RED, COLOR_DEFAULT, 0), \
+LINE(DIFF_INDEX, "index ", COLOR_BLUE, COLOR_DEFAULT, 0), \
+LINE(DIFF_OLDMODE, "old file mode ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DIFF_NEWMODE, "new file mode ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DIFF_COPY_FROM, "copy from", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DIFF_COPY_TO, "copy to", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DIFF_RENAME_FROM, "rename from", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DIFF_RENAME_TO, "rename to", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DIFF_SIMILARITY, "similarity ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DIFF_DISSIMILARITY,"dissimilarity ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DIFF_TREE, "diff-tree ", COLOR_BLUE, COLOR_DEFAULT, 0), \
+LINE(PP_AUTHOR, "Author: ", COLOR_CYAN, COLOR_DEFAULT, 0), \
+LINE(PP_COMMIT, "Commit: ", COLOR_MAGENTA, COLOR_DEFAULT, 0), \
+LINE(PP_MERGE, "Merge: ", COLOR_BLUE, COLOR_DEFAULT, 0), \
+LINE(PP_DATE, "Date: ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(PP_ADATE, "AuthorDate: ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(PP_CDATE, "CommitDate: ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(PP_REFS, "Refs: ", COLOR_RED, COLOR_DEFAULT, 0), \
+LINE(COMMIT, "commit ", COLOR_GREEN, COLOR_DEFAULT, 0), \
+LINE(PARENT, "parent ", COLOR_BLUE, COLOR_DEFAULT, 0), \
+LINE(TREE, "tree ", COLOR_BLUE, COLOR_DEFAULT, 0), \
+LINE(AUTHOR, "author ", COLOR_CYAN, COLOR_DEFAULT, 0), \
+LINE(COMMITTER, "committer ", COLOR_MAGENTA, COLOR_DEFAULT, 0), \
+LINE(SIGNOFF, " Signed-off-by", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(ACKED, " Acked-by", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DEFAULT, "", COLOR_DEFAULT, COLOR_DEFAULT, A_NORMAL), \
+LINE(CURSOR, "", COLOR_WHITE, COLOR_GREEN, A_BOLD), \
+LINE(STATUS, "", COLOR_GREEN, COLOR_DEFAULT, 0), \
+LINE(TITLE_BLUR, "", COLOR_WHITE, COLOR_BLUE, 0), \
+LINE(TITLE_FOCUS, "", COLOR_WHITE, COLOR_BLUE, A_BOLD), \
+LINE(MAIN_DATE, "", COLOR_BLUE, COLOR_DEFAULT, 0), \
+LINE(MAIN_AUTHOR, "", COLOR_GREEN, COLOR_DEFAULT, 0), \
+LINE(MAIN_COMMIT, "", COLOR_DEFAULT, COLOR_DEFAULT, 0), \
+LINE(MAIN_DELIM, "", COLOR_MAGENTA, COLOR_DEFAULT, 0), \
+LINE(MAIN_TAG, "", COLOR_MAGENTA, COLOR_DEFAULT, A_BOLD), \
+LINE(MAIN_REF, "", COLOR_CYAN, COLOR_DEFAULT, A_BOLD), \
+LINE(TREE_DIR, "", COLOR_DEFAULT, COLOR_DEFAULT, A_NORMAL), \
+LINE(TREE_FILE, "", COLOR_DEFAULT, COLOR_DEFAULT, A_NORMAL)
+
+enum line_type {
+#define LINE(type, line, fg, bg, attr) \
+ LINE_##type
+ LINE_INFO
+#undef LINE
+};
+
+struct line_info {
+ const char *name; /* Option name. */
+ int namelen; /* Size of option name. */
+ const char *line; /* The start of line to match. */
+ int linelen; /* Size of string to match. */
+ int fg, bg, attr; /* Color and text attributes for the lines. */
+};
+
+static struct line_info line_info[] = {
+#define LINE(type, line, fg, bg, attr) \
+ { #type, STRING_SIZE(#type), (line), STRING_SIZE(line), (fg), (bg), (attr) }
+ LINE_INFO
+#undef LINE
+};
+
+static enum line_type
+get_line_type(char *line)
+{
+ int linelen = strlen(line);
+ enum line_type type;
+
+ for (type = 0; type < ARRAY_SIZE(line_info); type++)
+ /* Case insensitive search matches Signed-off-by lines better. */
+ if (linelen >= line_info[type].linelen &&
+ !strncasecmp(line_info[type].line, line, line_info[type].linelen))
+ return type;
+
+ return LINE_DEFAULT;
+}
+
+static inline int
+get_line_attr(enum line_type type)
+{
+ assert(type < ARRAY_SIZE(line_info));
+ return COLOR_PAIR(type) | line_info[type].attr;
+}
+
+static struct line_info *
+get_line_info(char *name, int namelen)
+{
+ enum line_type type;
+
+ for (type = 0; type < ARRAY_SIZE(line_info); type++)
+ if (namelen == line_info[type].namelen &&
+ !string_enum_compare(line_info[type].name, name, namelen))
+ return &line_info[type];
+
+ return NULL;
+}
+
+static void
+init_colors(void)
+{
+ int default_bg = COLOR_BLACK;
+ int default_fg = COLOR_WHITE;
+ enum line_type type;
+
+ start_color();