Mercurial > audlegacy
comparison libaudacious/titlestring.c @ 0:cb178e5ad177 trunk
[svn] Import audacious source.
author | nenolod |
---|---|
date | Mon, 24 Oct 2005 03:06:47 -0700 |
parents | |
children | 6636d328fa38 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:cb178e5ad177 |
---|---|
1 /* | |
2 * Copyright (C) 2001, Espen Skoglund <esk@ira.uka.de> | |
3 * Copyright (C) 2001, Haavard Kvaalen <havardk@xmms.org> | |
4 * | |
5 * This program is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU General Public License | |
7 * as published by the Free Software Foundation; either version 2 | |
8 * of the License, or (at your option) any later version. | |
9 * | |
10 * This program is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 * GNU General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU General Public License | |
16 * along with this program; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA | |
18 * 02111-1307, USA. | |
19 * | |
20 */ | |
21 | |
22 #ifdef HAVE_CONFIG_H | |
23 # include "config.h" | |
24 #endif | |
25 | |
26 #define GETTEXT_PACKAGE PACKAGE | |
27 | |
28 #include <glib.h> | |
29 #include <glib/gi18n-lib.h> | |
30 #include <gtk/gtk.h> | |
31 #include <stdio.h> | |
32 #include <string.h> | |
33 | |
34 #include "titlestring.h" | |
35 | |
36 #define CHECK(input, field) \ | |
37 (((gchar *) &input->field - (gchar *) input) < input->__size) | |
38 | |
39 #define VS(input, field) (CHECK(input, field) ? input->field : NULL) | |
40 #define VI(input, field) (CHECK(input, field) ? input->field : 0) | |
41 | |
42 | |
43 BmpTitleInput * | |
44 bmp_title_input_new() | |
45 { | |
46 BmpTitleInput *input; | |
47 input = g_new0(BmpTitleInput, 1); | |
48 input->__size = XMMS_TITLEINPUT_SIZE; | |
49 input->__version = XMMS_TITLEINPUT_VERSION; | |
50 return input; | |
51 } | |
52 | |
53 void | |
54 bmp_title_input_free(BmpTitleInput * input) | |
55 { | |
56 if (!input) | |
57 return; | |
58 | |
59 g_free(input->performer); | |
60 g_free(input->album_name); | |
61 g_free(input->track_name); | |
62 g_free(input->date); | |
63 g_free(input->genre); | |
64 g_free(input->comment); | |
65 g_free(input->file_name); | |
66 g_free(input->file_path); | |
67 g_free(input); | |
68 } | |
69 | |
70 gchar * | |
71 xmms_get_titlestring(const gchar * fmt, TitleInput * input) | |
72 { | |
73 GString *outstr; | |
74 const gchar *string; | |
75 gchar c, convert[16]; | |
76 gint numdigits, numpr, val, i; | |
77 gint f_left, f_space, f_zero, someflag, width, precision; | |
78 gboolean did_output = FALSE; | |
79 gchar digits[] = "0123456789"; | |
80 | |
81 #define PUTCH(ch) g_string_append_c(outstr, ch) | |
82 | |
83 #define LEFTPAD(num) \ | |
84 G_STMT_START { \ | |
85 gint cnt = (num); \ | |
86 if ( ! f_left && cnt > 0 ) \ | |
87 while ( cnt-- > 0 ) \ | |
88 PUTCH(f_zero ? '0' : ' '); \ | |
89 } G_STMT_END; | |
90 | |
91 #define RIGHTPAD(num) \ | |
92 G_STMT_START { \ | |
93 gint cnt = (num); \ | |
94 if ( f_left && cnt > 0 ) \ | |
95 while ( cnt-- > 0 ) \ | |
96 PUTCH( ' ' ); \ | |
97 } G_STMT_END; | |
98 | |
99 if (fmt == NULL) | |
100 return NULL; | |
101 | |
102 outstr = g_string_new(""); | |
103 | |
104 for (;;) { | |
105 /* Copy characters until we encounter '%'. */ | |
106 while ((c = *fmt++) != '%') { | |
107 if (c == '\0') | |
108 goto Done; | |
109 g_string_append_c(outstr, c); | |
110 } | |
111 | |
112 f_left = f_space = f_zero = 0; | |
113 someflag = 1; | |
114 | |
115 | |
116 /* Parse flags. */ | |
117 while (someflag) { | |
118 switch (*fmt) { | |
119 case '-': | |
120 f_left = 1; | |
121 fmt++; | |
122 break; | |
123 case ' ': | |
124 f_space = 1; | |
125 fmt++; | |
126 break; | |
127 case '0': | |
128 f_zero = 1; | |
129 fmt++; | |
130 break; | |
131 default: | |
132 someflag = 0; | |
133 break; | |
134 } | |
135 } | |
136 | |
137 | |
138 /* Parse field width. */ | |
139 if ((c = *fmt) >= '0' && c <= '9') { | |
140 width = 0; | |
141 while ((c = *fmt++) >= '0' && c <= '9') { | |
142 width *= 10; | |
143 width += c - '0'; | |
144 } | |
145 fmt--; | |
146 } | |
147 else | |
148 width = -1; | |
149 | |
150 | |
151 /* Parse precision. */ | |
152 if (*fmt == '.') { | |
153 if ((c = *++fmt) >= '0' && c <= '9') { | |
154 precision = 0; | |
155 while ((c = *fmt++) >= '0' && c <= '9') { | |
156 precision *= 10; | |
157 precision += c - '0'; | |
158 } | |
159 fmt--; | |
160 } | |
161 else | |
162 precision = -1; | |
163 } | |
164 else | |
165 precision = -1; | |
166 | |
167 | |
168 /* Parse format conversion. */ | |
169 switch (c = *fmt++) { | |
170 case '}': /* close optional, just ignore */ | |
171 continue; | |
172 | |
173 case '{':{ /* optional entry: %{n:...%} */ | |
174 char n = *fmt++; | |
175 if (!((n == 'a' && VS(input, album_name)) || | |
176 (n == 'c' && VS(input, comment)) || | |
177 (n == 'd' && VS(input, date)) || | |
178 (n == 'e' && VS(input, file_ext)) || | |
179 (n == 'f' && VS(input, file_name)) || | |
180 (n == 'F' && VS(input, file_path)) || | |
181 (n == 'g' && VS(input, genre)) || | |
182 (n == 'n' && VI(input, track_number)) || | |
183 (n == 'p' && VS(input, performer)) || | |
184 (n == 't' && VS(input, track_name)))) { | |
185 int nl = 0; | |
186 char c; | |
187 while ((c = *fmt++)) /* until end of string */ | |
188 if (c == '}') /* if end of opt */ | |
189 if (!nl) | |
190 break; /* if outmost indent level */ | |
191 else | |
192 --nl; /* else reduce indent */ | |
193 else if (c == '{') | |
194 ++nl; /* increase indent */ | |
195 } | |
196 else | |
197 ++fmt; | |
198 break; | |
199 } | |
200 | |
201 case 'a': | |
202 string = VS(input, album_name); | |
203 goto Print_string; | |
204 case 'c': | |
205 string = VS(input, comment); | |
206 goto Print_string; | |
207 case 'd': | |
208 string = VS(input, date); | |
209 goto Print_string; | |
210 case 'e': | |
211 string = VS(input, file_ext); | |
212 goto Print_string; | |
213 case 'f': | |
214 string = VS(input, file_name); | |
215 goto Print_string; | |
216 case 'F': | |
217 string = VS(input, file_path); | |
218 goto Print_string; | |
219 case 'g': | |
220 string = VS(input, genre); | |
221 goto Print_string; | |
222 case 'n': | |
223 val = VI(input, track_number); | |
224 goto Print_number; | |
225 case 'p': | |
226 string = VS(input, performer); | |
227 goto Print_string; | |
228 case 't': | |
229 string = VS(input, track_name); | |
230 | |
231 Print_string: | |
232 if (string == NULL) | |
233 break; | |
234 did_output = TRUE; | |
235 | |
236 numpr = 0; | |
237 if (width > 0) { | |
238 /* Calculate printed size. */ | |
239 numpr = strlen(string); | |
240 if (precision >= 0 && precision < numpr) | |
241 numpr = precision; | |
242 | |
243 LEFTPAD(width - numpr); | |
244 } | |
245 | |
246 /* Insert string. */ | |
247 if (precision >= 0) { | |
248 while (precision-- > 0 && (c = *string++) != '\0') | |
249 PUTCH(c); | |
250 } | |
251 else { | |
252 while ((c = *string++) != '\0') | |
253 PUTCH(c); | |
254 } | |
255 | |
256 RIGHTPAD(width - numpr); | |
257 break; | |
258 | |
259 case 'y': | |
260 val = VI(input, year); | |
261 | |
262 Print_number: | |
263 if (val == 0) | |
264 break; | |
265 if (c != 'N') | |
266 did_output = TRUE; | |
267 | |
268 /* Create reversed number string. */ | |
269 numdigits = 0; | |
270 do { | |
271 convert[numdigits++] = digits[val % 10]; | |
272 val /= 10; | |
273 } | |
274 while (val > 0); | |
275 | |
276 numpr = numdigits > precision ? numdigits : precision; | |
277 | |
278 /* Insert left padding. */ | |
279 if (!f_left && width > numpr) { | |
280 if (f_zero) | |
281 numpr = width; | |
282 else | |
283 for (i = width - numpr; i-- > 0;) | |
284 PUTCH(' '); | |
285 } | |
286 | |
287 /* Insert zero padding. */ | |
288 for (i = numpr - numdigits; i-- > 0;) | |
289 PUTCH('0'); | |
290 | |
291 /* Insert number. */ | |
292 while (numdigits > 0) | |
293 PUTCH(convert[--numdigits]); | |
294 | |
295 RIGHTPAD(width - numpr); | |
296 break; | |
297 | |
298 case '%': | |
299 PUTCH('%'); | |
300 break; | |
301 | |
302 default: | |
303 PUTCH('%'); | |
304 PUTCH(c); | |
305 break; | |
306 } | |
307 } | |
308 | |
309 Done: | |
310 if (did_output) | |
311 return g_string_free(outstr, FALSE); | |
312 else | |
313 return NULL; | |
314 } | |
315 | |
316 struct _TagDescription { | |
317 gchar tag; | |
318 gchar *description; | |
319 }; | |
320 | |
321 typedef struct _TagDescription TagDescription; | |
322 | |
323 static TagDescription tag_descriptions[] = { | |
324 {'p', N_("Performer/Artist")}, | |
325 {'a', N_("Album")}, | |
326 {'g', N_("Genre")}, | |
327 {'f', N_("File name")}, | |
328 {'F', N_("File path")}, | |
329 {'e', N_("File extension")}, | |
330 {'t', N_("Track name")}, | |
331 {'n', N_("Track number")}, | |
332 {'d', N_("Date")}, | |
333 {'y', N_("Year")}, | |
334 {'c', N_("Comment")} | |
335 }; | |
336 | |
337 gint tag_descriptions_length = | |
338 sizeof(tag_descriptions) / sizeof(TagDescription); | |
339 | |
340 GtkWidget * | |
341 xmms_titlestring_descriptions(gchar * tags, gint columns) | |
342 { | |
343 GtkWidget *table, *label; | |
344 gchar tag_str[5]; | |
345 gint num = strlen(tags); | |
346 gint r = 0, c, i; | |
347 | |
348 g_return_val_if_fail(tags != NULL, NULL); | |
349 g_return_val_if_fail(columns <= num, NULL); | |
350 | |
351 table = gtk_table_new((num + columns - 1) / columns, columns * 2, FALSE); | |
352 gtk_table_set_row_spacings(GTK_TABLE(table), 2); | |
353 gtk_table_set_col_spacings(GTK_TABLE(table), 5); | |
354 | |
355 for (c = 0; c < columns; c++) { | |
356 for (r = 0; r < (num + columns - 1 - c) / columns; r++) { | |
357 g_snprintf(tag_str, sizeof(tag_str), "%%%c:", *tags); | |
358 label = gtk_label_new(tag_str); | |
359 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | |
360 gtk_table_attach(GTK_TABLE(table), label, 2 * c, 2 * c + 1, r, | |
361 r + 1, GTK_FILL, GTK_FILL, 0, 0); | |
362 gtk_widget_show(label); | |
363 | |
364 for (i = 0; i < tag_descriptions_length; i++) { | |
365 if (*tags == tag_descriptions[i].tag) { | |
366 label = gtk_label_new(_(tag_descriptions[i].description)); | |
367 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | |
368 gtk_table_attach(GTK_TABLE(table), label, 2 * c + 1, | |
369 2 * c + 2, r, r + 1, | |
370 GTK_EXPAND | GTK_FILL, | |
371 GTK_EXPAND | GTK_FILL, 0, 0); | |
372 gtk_widget_show(label); | |
373 break; | |
374 } | |
375 } | |
376 | |
377 if (i == tag_descriptions_length) | |
378 g_warning("Invalid tag: %c", *tags); | |
379 | |
380 tags++; | |
381 } | |
382 | |
383 } | |
384 | |
385 label = gtk_label_new(_("%{n:...%}: Display \"...\" only if element " | |
386 "%n is present")); | |
387 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); | |
388 gtk_table_attach(GTK_TABLE(table), label, 0, r + 1, | |
389 r + 1, r + 2, GTK_FILL, GTK_FILL, 0, 0); | |
390 gtk_widget_show(label); | |
391 | |
392 return table; | |
393 } |