1 /* Copyright (c) 2006-2014 Jonas Fonseca <jonas.fonseca@gmail.com>
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU General Public License as
5 * published by the Free Software Foundation; either version 2 of
6 * the License, or (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
15 #include "tig/types.h"
16 #include "tig/refdb.h"
20 static struct line_rule
*line_rule
;
21 static size_t line_rules
;
23 static struct line_info
**color_pair
;
24 static size_t color_pairs
;
26 DEFINE_ALLOCATOR(realloc_line_rule
, struct line_rule
, 8)
27 DEFINE_ALLOCATOR(realloc_color_pair
, struct line_info
*, 8)
30 get_line_type(const char *line
)
32 int linelen
= strlen(line
);
35 for (type
= 0; type
< line_rules
; type
++) {
36 struct line_rule
*rule
= &line_rule
[type
];
38 /* Case insensitive search matches Signed-off-by lines better. */
39 if (rule
->linelen
&& linelen
>= rule
->linelen
&&
40 !strncasecmp(rule
->line
, line
, rule
->linelen
))
48 get_line_type_from_ref(const struct ref
*ref
)
50 if (ref
->type
== REFERENCE_HEAD
)
51 return LINE_MAIN_HEAD
;
52 else if (ref
->type
== REFERENCE_LOCAL_TAG
)
53 return LINE_MAIN_LOCAL_TAG
;
54 else if (ref
->type
== REFERENCE_TAG
)
56 else if (ref
->type
== REFERENCE_TRACKED_REMOTE
)
57 return LINE_MAIN_TRACKED
;
58 else if (ref
->type
== REFERENCE_REMOTE
)
59 return LINE_MAIN_REMOTE
;
60 else if (ref
->type
== REFERENCE_REPLACE
)
61 return LINE_MAIN_REPLACE
;
67 get_line_info(const char *prefix
, enum line_type type
)
69 struct line_info
*info
;
70 struct line_rule
*rule
;
72 assert(type
< line_rules
);
73 rule
= &line_rule
[type
];
74 for (info
= &rule
->info
; info
; info
= info
->next
) {
75 if (prefix
&& info
->prefix
== prefix
)
77 if (!prefix
&& !info
->prefix
)
84 static struct line_info
*
85 init_line_info(const char *prefix
, const char *name
, size_t namelen
, const char *line
, size_t linelen
)
87 struct line_rule
*rule
;
89 if (!realloc_line_rule(&line_rule
, line_rules
, 1))
90 die("Failed to allocate line info");
92 rule
= &line_rule
[line_rules
++];
94 rule
->namelen
= namelen
;
96 rule
->linelen
= linelen
;
98 rule
->info
.prefix
= prefix
;
99 rule
->info
.fg
= COLOR_DEFAULT
;
100 rule
->info
.bg
= COLOR_DEFAULT
;
105 #define INIT_BUILTIN_LINE_INFO(type, line) \
106 init_line_info(NULL, #type, STRING_SIZE(#type), (line), STRING_SIZE(line))
108 static struct line_rule
*
109 find_line_rule(struct line_rule
*query
)
114 LINE_INFO(INIT_BUILTIN_LINE_INFO
);
117 for (type
= 0; type
< line_rules
; type
++) {
118 struct line_rule
*rule
= &line_rule
[type
];
120 if (query
->namelen
&& enum_equals(*rule
, query
->name
, query
->namelen
))
123 if (query
->linelen
&& query
->linelen
== rule
->linelen
&&
124 !strncasecmp(rule
->line
, query
->line
, rule
->linelen
))
132 add_line_rule(const char *prefix
, struct line_rule
*query
)
134 struct line_rule
*rule
= find_line_rule(query
);
135 struct line_info
*info
, *last
;
142 query
->line
= strndup(query
->line
, query
->linelen
);
145 return init_line_info(prefix
, "", 0, query
->line
, query
->linelen
);
148 for (info
= &rule
->info
; info
; last
= info
, info
= info
->next
)
149 if (info
->prefix
== prefix
)
152 info
= calloc(1, sizeof(*info
));
154 info
->prefix
= prefix
;
160 init_line_info_color_pair(struct line_info
*info
, enum line_type type
,
161 int default_bg
, int default_fg
)
163 int bg
= info
->bg
== COLOR_DEFAULT
? default_bg
: info
->bg
;
164 int fg
= info
->fg
== COLOR_DEFAULT
? default_fg
: info
->fg
;
167 for (i
= 0; i
< color_pairs
; i
++) {
168 if (color_pair
[i
]->fg
== info
->fg
&& color_pair
[i
]->bg
== info
->bg
) {
169 info
->color_pair
= i
;
174 if (!realloc_color_pair(&color_pair
, color_pairs
, 1))
175 die("Failed to alloc color pair");
177 color_pair
[color_pairs
] = info
;
178 info
->color_pair
= color_pairs
++;
179 init_pair(COLOR_ID(info
->color_pair
), fg
, bg
);
185 struct line_rule query
= { "default", STRING_SIZE("default") };
186 struct line_rule
*rule
= find_line_rule(&query
);
187 int default_bg
= rule
->info
.bg
;
188 int default_fg
= rule
->info
.fg
;
191 /* XXX: Even if the terminal does not support colors (e.g.
192 * TERM=dumb) init_colors() must ensure that the built-in rules
193 * have been initialized. This is done by the above call to
194 * find_line_rule(). */
200 if (assume_default_colors(default_fg
, default_bg
) == ERR
) {
201 default_bg
= COLOR_BLACK
;
202 default_fg
= COLOR_WHITE
;
205 for (type
= 0; type
< line_rules
; type
++) {
206 struct line_rule
*rule
= &line_rule
[type
];
207 struct line_info
*info
;
209 for (info
= &rule
->info
; info
; info
= info
->next
) {
210 init_line_info_color_pair(info
, type
, default_bg
, default_fg
);
215 /* vim: set ts=8 sw=8 noexpandtab: */