+#define LINE_INFO \
+/* Line type String to match Foreground Background Attributes
+ * --------- --------------- ---------- ---------- ---------- */ \
+/* Diff markup */ \
+LINE(DIFF, "diff --git ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DIFF_INDEX, "index ", COLOR_BLUE, 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_OLDMODE, "old file mode ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DIFF_NEWMODE, "new file mode ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DIFF_COPY, "copy ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DIFF_RENAME, "rename ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DIFF_SIM, "similarity ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+LINE(DIFF_DISSIM, "dissimilarity ", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+/* Pretty print commit header */ \
+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), \
+/* Raw commit header */ \
+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), \
+/* Misc */ \
+LINE(DIFF_TREE, "diff-tree ", COLOR_BLUE, COLOR_DEFAULT, 0), \
+LINE(SIGNOFF, " Signed-off-by", COLOR_YELLOW, COLOR_DEFAULT, 0), \
+/* UI colors */ \
+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),
+
+enum line_type {
+#define LINE(type, line, fg, bg, attr) \
+ LINE_##type
+ LINE_INFO
+#undef LINE
+};
+
+struct line_info {
+ 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) \
+ { (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 void
+init_colors(void)
+{
+ int default_bg = COLOR_BLACK;
+ int default_fg = COLOR_WHITE;
+ enum line_type type;
+
+ start_color();
+
+ if (use_default_colors() != ERR) {
+ default_bg = -1;
+ default_fg = -1;
+ }
+
+ for (type = 0; type < ARRAY_SIZE(line_info); type++) {
+ struct line_info *info = &line_info[type];
+ int bg = info->bg == COLOR_DEFAULT ? default_bg : info->bg;
+ int fg = info->fg == COLOR_DEFAULT ? default_fg : info->fg;
+
+ init_pair(type, fg, bg);
+ }
+}