1 // vim:ts=4:sw=4:expandtab
2 #include <config.h>
3 #include <stdbool.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <sys/types.h>
9 #include <fcntl.h>
10 #include <dirent.h>
11 #include <ctype.h>
12
13 #include "i3status.h"
14
15 /*
16 * Returns the correct color format for dzen (^fg(color)), xmobar (<fc=color>)
17 * or lemonbar (%{Fcolor})
18 *
19 */
color(const char * colorstr)20 char *color(const char *colorstr) {
21 static char colorbuf[32];
22 if (!cfg_getbool(cfg_general, "colors")) {
23 colorbuf[0] = '\0';
24 return colorbuf;
25 }
26 if (output_format == O_DZEN2)
27 (void)snprintf(colorbuf, sizeof(colorbuf), "^fg(%s)", cfg_getstr(cfg_general, colorstr));
28 else if (output_format == O_XMOBAR)
29 (void)snprintf(colorbuf, sizeof(colorbuf), "<fc=%s>", cfg_getstr(cfg_general, colorstr));
30 else if (output_format == O_LEMONBAR)
31 (void)snprintf(colorbuf, sizeof(colorbuf), "%%{F%s}", cfg_getstr(cfg_general, colorstr));
32 else if (output_format == O_TERM) {
33 /* The escape-sequence for color is <CSI><col>;1m (bright/bold
34 * output), where col is a 3-bit rgb-value with b in the
35 * least-significant bit. We round the given color to the
36 * nearist 3-bit-depth color and output the escape-sequence */
37 char *str = cfg_getstr(cfg_general, colorstr);
38 int col = strtol(str + 1, NULL, 16);
39 int r = (col & (0xFF << 0)) / 0x80;
40 int g = (col & (0xFF << 8)) / 0x8000;
41 int b = (col & (0xFF << 16)) / 0x800000;
42 col = (r << 2) | (g << 1) | b;
43 (void)snprintf(colorbuf, sizeof(colorbuf), "\033[3%d;1m", col);
44 }
45 return colorbuf;
46 }
47
48 /*
49 * Some color formats (xmobar) require to terminate colors again
50 *
51 */
endcolor(void)52 char *endcolor(void) {
53 if (output_format == O_XMOBAR)
54 return "</fc>";
55 else if (output_format == O_TERM)
56 return "\033[0m";
57 else
58 return "";
59 }
60
print_separator(const char * separator)61 void print_separator(const char *separator) {
62 if (output_format == O_I3BAR || strlen(separator) == 0)
63 return;
64
65 if (output_format == O_DZEN2)
66 printf("^fg(%s)%s^fg()", cfg_getstr(cfg_general, "color_separator"), separator);
67 else if (output_format == O_XMOBAR)
68 printf("<fc=%s>%s</fc>", cfg_getstr(cfg_general, "color_separator"), separator);
69 else if (output_format == O_LEMONBAR)
70 printf("%%{F%s}%s%%{F-}", cfg_getstr(cfg_general, "color_separator"), separator);
71 else if (output_format == O_TERM)
72 printf("%s%s%s", color("color_separator"), separator, endcolor());
73 else if (output_format == O_NONE)
74 printf("%s", separator);
75 }
76
77 /*
78 * The term-output hides the cursor. We call this on exit to reset that.
79 */
reset_cursor(void)80 void reset_cursor(void) {
81 printf("\033[?25h");
82 }
83
84 /*
85 * Escapes ampersand, less-than, greater-than, single-quote, and double-quote
86 * characters with the corresponding Pango markup strings if markup is enabled.
87 * See the glib implementation:
88 * https://git.gnome.org/browse/glib/tree/glib/gmarkup.c?id=03db1f455b4265654e237d2ad55464b4113cba8a#n2142
89 *
90 */
maybe_escape_markup(char * text,char ** buffer)91 void maybe_escape_markup(char *text, char **buffer) {
92 if (markup_format == M_NONE) {
93 *buffer += sprintf(*buffer, "%s", text);
94 return;
95 }
96 for (; *text != '\0'; text++) {
97 switch (*text) {
98 case '&':
99 *buffer += sprintf(*buffer, "%s", "&");
100 break;
101 case '<':
102 *buffer += sprintf(*buffer, "%s", "<");
103 break;
104 case '>':
105 *buffer += sprintf(*buffer, "%s", ">");
106 break;
107 case '\'':
108 *buffer += sprintf(*buffer, "%s", "'");
109 break;
110 case '"':
111 *buffer += sprintf(*buffer, "%s", """);
112 break;
113 default:
114 if ((0x1 <= *text && *text <= 0x8) ||
115 (0xb <= *text && *text <= 0xc) ||
116 (0xe <= *text && *text <= 0x1f)) {
117 *buffer += sprintf(*buffer, "&#x%x;", *text);
118 } else {
119 *(*buffer)++ = *text;
120 }
121 break;
122 }
123 }
124 }
125
126 /*
127 * remove leading spaces
128 */
ltrim(const char * s)129 char *ltrim(const char *s) {
130 while (isspace(*s))
131 ++s;
132 return sstrdup(s);
133 }
134
135 /*
136 * remove trailing spaces
137 */
rtrim(const char * s)138 char *rtrim(const char *s) {
139 char *r = sstrdup(s);
140 if (r != NULL) {
141 char *fr = r + strlen(s) - 1;
142 while ((isspace(*fr) || *fr == 0) && fr >= r)
143 --fr;
144 *++fr = 0;
145 }
146 return r;
147 }
148
149 /*
150 * remove leading & trailing spaces
151 */
trim(const char * s)152 char *trim(const char *s) {
153 char *r = rtrim(s);
154 char *f = ltrim(r);
155 free(r);
156 return f;
157 }