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