Code

moved code to charset.c
[ncmpc.git] / src / strfsong.c
1 /* 
2  * $Id$
3  *
4  * Based on mpc's songToFormatedString modified for glib and ncmpc
5  *
6  *
7  * (c) 2003-2004 by normalperson and Warren Dukes (shank@mercury.chem.pitt.edu)
8  *              and Daniel Brown (danb@cs.utexas.edu)
9  *              and Kalle Wallin (kaw@linux.se)
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  */
25 #include "strfsong.h"
26 #include "support.h"
27 #include "charset.h"
29 #include <string.h>
31 static const gchar *
32 skip(const gchar * p)
33 {
34         gint stack = 0;
36         while (*p != '\0') {
37                 if(*p == '[') stack++;
38                 if(*p == '#' && p[1] != '\0') {
39                         /* skip escaped stuff */
40                         ++p;
41                 } else if(stack) {
42                         if(*p == ']') stack--;
43                 } else {
44                         if(*p == '&' || *p == '|' || *p == ']') {
45                                 break;
46                         }
47                 }
48                 ++p;
49         }
51         return p;
52 }
54 static gsize
55 _strfsong(gchar *s,
56           gsize max,
57           const gchar *format,
58           const struct mpd_song *song,
59           const gchar **last)
60 {
61         const gchar *p, *end;
62         gchar *temp;
63         gsize n, length = 0;
64         gboolean found = FALSE;
66         memset(s, 0, max);
67         if( song==NULL )
68                 return 0;
70         for (p = format; *p != '\0' && length<max;) {
71                 /* OR */
72                 if (p[0] == '|') {
73                         ++p;
74                         if(!found) {
75                                 memset(s, 0, max);
76                                 length = 0;
77                         } else {
78                                 p = skip(p);
79                         }
80                         continue;
81                 }
83                 /* AND */
84                 if (p[0] == '&') {
85                         ++p;
86                         if(!found) {
87                                 p = skip(p);
88                         } else {
89                                 found = FALSE;
90                         }
91                         continue;
92                 }
94                 /* EXPRESSION START */
95                 if (p[0] == '[') {
96                         temp = g_malloc0(max);
97                         if( _strfsong(temp, max, p+1, song, &p) >0 ) {
98                                 g_strlcat(s, temp, max);
99                                 length = strlen(s);
100                                 found = TRUE;
101                         }
102                         g_free(temp);
103                         continue;
104                 }
106                 /* EXPRESSION END */
107                 if (p[0] == ']') {
108                         if(last) *last = p+1;
109                         if(!found && length) {
110                                 memset(s, 0, max);
111                                 length = 0;
112                         }
113                         return length;
114                 }
116                 /* pass-through non-escaped portions of the format string */
117                 if (p[0] != '#' && p[0] != '%' && length<max) {
118                         s[length++] = *p;
119                         p++;
120                         continue;
121                 }
123                 /* let the escape character escape itself */
124                 if (p[0] == '#' && p[1] != '\0' && length<max) {
125                         s[length++] = *(p+1);
126                         p+=2;
127                         continue;
128                 }
130                 /* advance past the esc character */
132                 /* find the extent of this format specifier (stop at \0, ' ', or esc) */
133                 temp = NULL;
134                 end  = p+1;
135                 while(*end >= 'a' && *end <= 'z') {
136                         end++;
137                 }
138                 n = end - p + 1;
139                 if(*end != '%')
140                         n--;
141                 else if (strncmp("%file%", p, n) == 0)
142                         temp = utf8_to_locale(song->file);
143                 else if (strncmp("%artist%", p, n) == 0)
144                         temp = song->artist ? utf8_to_locale(song->artist) : NULL;
145                 else if (strncmp("%title%", p, n) == 0)
146                         temp = song->title ? utf8_to_locale(song->title) : NULL;
147                 else if (strncmp("%album%", p, n) == 0)
148                         temp = song->album ? utf8_to_locale(song->album) : NULL;
149                 else if (strncmp("%shortalbum%", p, n) == 0) {
150                         temp = song->album ? utf8_to_locale(song->album) : NULL;
151                         if (temp) {
152                                 gchar *temp2 = g_strndup(temp, 25);
153                                 if (strlen(temp) > 25) {
154                                         temp2[24] = '.';
155                                         temp2[23] = '.';
156                                         temp2[22] = '.';
157                                 }
158                                 g_free(temp);
159                                 temp = temp2;
160                         }
161                 }
162                 else if (strncmp("%track%", p, n) == 0)
163                         temp = song->track ? utf8_to_locale(song->track) : NULL;
164                 else if (strncmp("%name%", p, n) == 0)
165                         temp = song->name ? utf8_to_locale(song->name) : NULL;
166                 else if (strncmp("%date%", p, n) == 0)
167                         temp = song->date ? utf8_to_locale(song->date) : NULL;
168                 else if (strncmp("%genre%", p, n) == 0)
169                         temp = song->genre ? utf8_to_locale(song->genre) : NULL;
170                 else if (strncmp("%shortfile%", p, n) == 0) {
171                         if( strstr(song->file, "://") )
172                                 temp = utf8_to_locale(song->file);
173                         else
174                                 temp = utf8_to_locale(basename(song->file));
175                 } else if (strncmp("%time%", p, n) == 0) {
176                         if (song->time != MPD_SONG_NO_TIME)  {
177                                 if (song->time > 3600) {
178                                         temp = g_strdup_printf("%d:%02d:%02d",
179                                                                song->time / 3600,
180                                                                (song->time % 3600) / 60,
181                                                                song->time % 60);
182                                 } else {
183                                         temp = g_strdup_printf("%d:%02d",
184                                                                song->time / 60,
185                                                                song->time % 60);
186                                 }
187                         }
188                 }
190                 if( temp == NULL) {
191                         gsize templen=n;
192                         /* just pass-through any unknown specifiers (including esc) */
193                         /* drop a null char in so printf stops at the end of this specifier,
194                            but put the real character back in (pseudo-const) */
195                         if( length+templen > max )
196                                 templen = max-length;
197                         g_strlcat(s, p,max);
198                         length+=templen;
199                 } else {
200                         gsize templen = strlen(temp);
202                         found = TRUE;
203                         if( length+templen > max )
204                                 templen = max-length;
205                         g_strlcat(s, temp, max);
206                         length+=templen;
207                         g_free(temp);
208                 }
210                 /* advance past the specifier */
211                 p += n;
212         }
214         if(last) *last = p;
216         return length;
219 gsize
220 strfsong(gchar *s, gsize max, const gchar *format,
221          const struct mpd_song *song)
223   return _strfsong(s, max, format, song, NULL);
225