A tiling window manager
1/*
2 * Copyright (C) 2006 Antti Nyk�nen <aon@iki.fi>
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the Free
6 * Software Foundation; either version 2 of the License, or (at your option)
7 * any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place, Suite 330, Boston, MA 02111-1307 USA.
17 */
18
19#include <ctype.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include "sdorfehs.h"
24
25/* Function prototypes for format char expanders. */
26#define RP_FMT(fn) static void fmt_ ## fn (rp_window_elem *elem, struct sbuf *buf)
27RP_FMT(framenum);
28RP_FMT(lastaccess);
29RP_FMT(name);
30RP_FMT(number);
31RP_FMT(resname);
32RP_FMT(resclass);
33RP_FMT(status);
34RP_FMT(windowid);
35RP_FMT(height);
36RP_FMT(width);
37RP_FMT(incheight);
38RP_FMT(incwidth);
39RP_FMT(gravity);
40RP_FMT(screen);
41RP_FMT(xrandrscreen);
42RP_FMT(transient);
43RP_FMT(maxsize);
44RP_FMT(pid);
45
46struct fmt_item {
47 /* The format character */
48 char fmt_char;
49
50 /* Callback to return the expanded string. */
51 void (*fmt_fn) (rp_window_elem *, struct sbuf *);
52};
53
54struct fmt_item fmt_items[] = {
55 {'a', fmt_resname},
56 {'g', fmt_gravity},
57 {'h', fmt_height},
58 {'H', fmt_incheight},
59 {'c', fmt_resclass},
60 {'f', fmt_framenum},
61 {'i', fmt_windowid},
62 {'l', fmt_lastaccess},
63 {'M', fmt_maxsize},
64 {'n', fmt_number},
65 {'p', fmt_pid},
66 {'s', fmt_status},
67 {'S', fmt_screen},
68 {'t', fmt_name},
69 {'T', fmt_transient},
70 {'w', fmt_width},
71 {'W', fmt_incwidth},
72 {'x', fmt_xrandrscreen},
73 {0, NULL}
74};
75
76void
77format_string(char *fmt, rp_window_elem *win_elem, struct sbuf *buffer)
78{
79#define STATE_READ 0
80#define STATE_NUMBER 1
81#define STATE_ESCAPE 2
82 int state = STATE_READ;
83 char dbuf[10];
84 int width = -1;
85 struct sbuf *retbuf;
86 int fip, found;
87
88 retbuf = sbuf_new(0);
89
90 for (; *fmt; fmt++) {
91 if (*fmt == '%' && state == STATE_READ) {
92 state = STATE_ESCAPE;
93 continue;
94 }
95 if ((state == STATE_ESCAPE || state == STATE_NUMBER) &&
96 isdigit(*fmt)) {
97 /* Accumulate the width one digit at a time. */
98 if (state == STATE_ESCAPE)
99 width = 0;
100 width *= 10;
101 width += *fmt - '0';
102 state = STATE_NUMBER;
103 continue;
104 }
105 found = 0;
106 if (state == STATE_ESCAPE || state == STATE_NUMBER) {
107 if (*fmt == '%')
108 sbuf_concat(buffer, "%");
109 else {
110 for (fip = 0; fmt_items[fip].fmt_char; fip++) {
111 if (fmt_items[fip].fmt_char == *fmt) {
112 sbuf_clear(retbuf);
113 fmt_items[fip].fmt_fn(win_elem,
114 retbuf);
115 sbuf_utf8_nconcat(buffer,
116 sbuf_get(retbuf), width);
117 found = 1;
118 break;
119 }
120 }
121 if (!found) {
122 sbuf_printf_concat(buffer, "%%%c", *fmt);
123 break;
124 }
125 }
126 state = STATE_READ;
127 width = -1;
128 } else {
129 /* Insert the character. */
130 dbuf[0] = *fmt;
131 dbuf[1] = 0;
132 sbuf_concat(buffer, dbuf);
133 }
134 }
135 sbuf_free(retbuf);
136#undef STATE_READ
137#undef STATE_ESCAPE
138#undef STATE_NUMBER
139}
140
141static void
142fmt_framenum(rp_window_elem *win_elem, struct sbuf *buf)
143{
144 if (win_elem->win->frame_number != EMPTY) {
145 sbuf_printf_concat(buf, "%d", win_elem->win->frame_number);
146 } else
147 sbuf_copy(buf, " ");
148}
149
150static void
151fmt_lastaccess(rp_window_elem *win_elem, struct sbuf *buf)
152{
153 sbuf_printf_concat(buf, "%d", win_elem->win->last_access);
154}
155
156static void
157fmt_name(rp_window_elem *win_elem, struct sbuf *buf)
158{
159 sbuf_copy(buf, window_name(win_elem->win));
160}
161
162static void
163fmt_number(rp_window_elem *win_elem, struct sbuf *buf)
164{
165 sbuf_printf_concat(buf, "%d", win_elem->number);
166}
167
168static void
169fmt_resname(rp_window_elem *win_elem, struct sbuf *buf)
170{
171 if (win_elem->win->res_name)
172 sbuf_copy(buf, win_elem->win->res_name);
173 else
174 sbuf_copy(buf, "None");
175}
176
177static void
178fmt_resclass(rp_window_elem *win_elem, struct sbuf *buf)
179{
180 if (win_elem->win->res_class)
181 sbuf_copy(buf, win_elem->win->res_class);
182 else
183 sbuf_copy(buf, "None");
184}
185
186static void
187fmt_status(rp_window_elem *win_elem, struct sbuf *buf)
188{
189 rp_window *other_window;
190
191 other_window = find_window_other(rp_current_vscreen);
192 if (win_elem->win == other_window)
193 sbuf_copy(buf, "+");
194 else if (win_elem->win == current_window())
195 sbuf_copy(buf, "*");
196 else
197 sbuf_copy(buf, "-");
198}
199
200static void
201fmt_windowid(rp_window_elem *elem, struct sbuf *buf)
202{
203 sbuf_printf_concat(buf, "%ld", (unsigned long) elem->win->w);
204}
205
206static void
207fmt_height(rp_window_elem *elem, struct sbuf *buf)
208{
209 sbuf_printf_concat(buf, "%d", elem->win->height);
210}
211
212static void
213fmt_width(rp_window_elem *elem, struct sbuf *buf)
214{
215 sbuf_printf_concat(buf, "%d", elem->win->width);
216}
217
218static void
219fmt_incheight(rp_window_elem *elem, struct sbuf *buf)
220{
221 int height;
222 height = elem->win->height;
223
224 if (elem->win->hints->flags & PResizeInc)
225 height /= elem->win->hints->height_inc;
226
227 sbuf_printf_concat(buf, "%d", height);
228}
229
230static void
231fmt_incwidth(rp_window_elem *elem, struct sbuf *buf)
232{
233 int width;
234 width = elem->win->width;
235
236 if (elem->win->hints->flags & PResizeInc)
237 width /= elem->win->hints->width_inc;
238
239 sbuf_printf_concat(buf, "%d", width);
240}
241
242static void
243fmt_gravity(rp_window_elem *elem, struct sbuf *buf)
244{
245 sbuf_copy(buf, wingravity_to_string(elem->win->gravity));
246}
247
248static void
249fmt_screen(rp_window_elem *elem, struct sbuf *buf)
250{
251 sbuf_printf_concat(buf, "%d", elem->win->vscreen->screen->screen_num);
252}
253
254static void
255fmt_xrandrscreen(rp_window_elem *elem, struct sbuf *buf)
256{
257 sbuf_printf_concat(buf, "%d", elem->win->vscreen->screen->xrandr.output);
258}
259
260static void
261fmt_transient(rp_window_elem *elem, struct sbuf *buf)
262{
263 if (elem->win->transient)
264 sbuf_concat(buf, "Transient");
265}
266
267static void
268fmt_maxsize(rp_window_elem *elem, struct sbuf *buf)
269{
270 if (elem->win->hints->flags & PMaxSize)
271 sbuf_concat(buf, "Maxsize");
272}
273
274static void
275fmt_pid(rp_window_elem *elem, struct sbuf *buf)
276{
277 struct rp_child_info *info;
278
279 info = get_child_info(elem->win->w, 0);
280 if (info)
281 sbuf_printf_concat(buf, "%d", info->pid);
282 else
283 sbuf_concat(buf, "?");
284}