Mercurial > audlegacy
diff libaudacious/titlestring.c @ 0:cb178e5ad177 trunk
[svn] Import audacious source.
author | nenolod |
---|---|
date | Mon, 24 Oct 2005 03:06:47 -0700 |
parents | |
children | 6636d328fa38 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libaudacious/titlestring.c Mon Oct 24 03:06:47 2005 -0700 @@ -0,0 +1,393 @@ +/* + * Copyright (C) 2001, Espen Skoglund <esk@ira.uka.de> + * Copyright (C) 2001, Haavard Kvaalen <havardk@xmms.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define GETTEXT_PACKAGE PACKAGE + +#include <glib.h> +#include <glib/gi18n-lib.h> +#include <gtk/gtk.h> +#include <stdio.h> +#include <string.h> + +#include "titlestring.h" + +#define CHECK(input, field) \ + (((gchar *) &input->field - (gchar *) input) < input->__size) + +#define VS(input, field) (CHECK(input, field) ? input->field : NULL) +#define VI(input, field) (CHECK(input, field) ? input->field : 0) + + +BmpTitleInput * +bmp_title_input_new() +{ + BmpTitleInput *input; + input = g_new0(BmpTitleInput, 1); + input->__size = XMMS_TITLEINPUT_SIZE; + input->__version = XMMS_TITLEINPUT_VERSION; + return input; +} + +void +bmp_title_input_free(BmpTitleInput * input) +{ + if (!input) + return; + + g_free(input->performer); + g_free(input->album_name); + g_free(input->track_name); + g_free(input->date); + g_free(input->genre); + g_free(input->comment); + g_free(input->file_name); + g_free(input->file_path); + g_free(input); +} + +gchar * +xmms_get_titlestring(const gchar * fmt, TitleInput * input) +{ + GString *outstr; + const gchar *string; + gchar c, convert[16]; + gint numdigits, numpr, val, i; + gint f_left, f_space, f_zero, someflag, width, precision; + gboolean did_output = FALSE; + gchar digits[] = "0123456789"; + +#define PUTCH(ch) g_string_append_c(outstr, ch) + +#define LEFTPAD(num) \ + G_STMT_START { \ + gint cnt = (num); \ + if ( ! f_left && cnt > 0 ) \ + while ( cnt-- > 0 ) \ + PUTCH(f_zero ? '0' : ' '); \ + } G_STMT_END; + +#define RIGHTPAD(num) \ + G_STMT_START { \ + gint cnt = (num); \ + if ( f_left && cnt > 0 ) \ + while ( cnt-- > 0 ) \ + PUTCH( ' ' ); \ + } G_STMT_END; + + if (fmt == NULL) + return NULL; + + outstr = g_string_new(""); + + for (;;) { + /* Copy characters until we encounter '%'. */ + while ((c = *fmt++) != '%') { + if (c == '\0') + goto Done; + g_string_append_c(outstr, c); + } + + f_left = f_space = f_zero = 0; + someflag = 1; + + + /* Parse flags. */ + while (someflag) { + switch (*fmt) { + case '-': + f_left = 1; + fmt++; + break; + case ' ': + f_space = 1; + fmt++; + break; + case '0': + f_zero = 1; + fmt++; + break; + default: + someflag = 0; + break; + } + } + + + /* Parse field width. */ + if ((c = *fmt) >= '0' && c <= '9') { + width = 0; + while ((c = *fmt++) >= '0' && c <= '9') { + width *= 10; + width += c - '0'; + } + fmt--; + } + else + width = -1; + + + /* Parse precision. */ + if (*fmt == '.') { + if ((c = *++fmt) >= '0' && c <= '9') { + precision = 0; + while ((c = *fmt++) >= '0' && c <= '9') { + precision *= 10; + precision += c - '0'; + } + fmt--; + } + else + precision = -1; + } + else + precision = -1; + + + /* Parse format conversion. */ + switch (c = *fmt++) { + case '}': /* close optional, just ignore */ + continue; + + case '{':{ /* optional entry: %{n:...%} */ + char n = *fmt++; + if (!((n == 'a' && VS(input, album_name)) || + (n == 'c' && VS(input, comment)) || + (n == 'd' && VS(input, date)) || + (n == 'e' && VS(input, file_ext)) || + (n == 'f' && VS(input, file_name)) || + (n == 'F' && VS(input, file_path)) || + (n == 'g' && VS(input, genre)) || + (n == 'n' && VI(input, track_number)) || + (n == 'p' && VS(input, performer)) || + (n == 't' && VS(input, track_name)))) { + int nl = 0; + char c; + while ((c = *fmt++)) /* until end of string */ + if (c == '}') /* if end of opt */ + if (!nl) + break; /* if outmost indent level */ + else + --nl; /* else reduce indent */ + else if (c == '{') + ++nl; /* increase indent */ + } + else + ++fmt; + break; + } + + case 'a': + string = VS(input, album_name); + goto Print_string; + case 'c': + string = VS(input, comment); + goto Print_string; + case 'd': + string = VS(input, date); + goto Print_string; + case 'e': + string = VS(input, file_ext); + goto Print_string; + case 'f': + string = VS(input, file_name); + goto Print_string; + case 'F': + string = VS(input, file_path); + goto Print_string; + case 'g': + string = VS(input, genre); + goto Print_string; + case 'n': + val = VI(input, track_number); + goto Print_number; + case 'p': + string = VS(input, performer); + goto Print_string; + case 't': + string = VS(input, track_name); + + Print_string: + if (string == NULL) + break; + did_output = TRUE; + + numpr = 0; + if (width > 0) { + /* Calculate printed size. */ + numpr = strlen(string); + if (precision >= 0 && precision < numpr) + numpr = precision; + + LEFTPAD(width - numpr); + } + + /* Insert string. */ + if (precision >= 0) { + while (precision-- > 0 && (c = *string++) != '\0') + PUTCH(c); + } + else { + while ((c = *string++) != '\0') + PUTCH(c); + } + + RIGHTPAD(width - numpr); + break; + + case 'y': + val = VI(input, year); + + Print_number: + if (val == 0) + break; + if (c != 'N') + did_output = TRUE; + + /* Create reversed number string. */ + numdigits = 0; + do { + convert[numdigits++] = digits[val % 10]; + val /= 10; + } + while (val > 0); + + numpr = numdigits > precision ? numdigits : precision; + + /* Insert left padding. */ + if (!f_left && width > numpr) { + if (f_zero) + numpr = width; + else + for (i = width - numpr; i-- > 0;) + PUTCH(' '); + } + + /* Insert zero padding. */ + for (i = numpr - numdigits; i-- > 0;) + PUTCH('0'); + + /* Insert number. */ + while (numdigits > 0) + PUTCH(convert[--numdigits]); + + RIGHTPAD(width - numpr); + break; + + case '%': + PUTCH('%'); + break; + + default: + PUTCH('%'); + PUTCH(c); + break; + } + } + + Done: + if (did_output) + return g_string_free(outstr, FALSE); + else + return NULL; +} + +struct _TagDescription { + gchar tag; + gchar *description; +}; + +typedef struct _TagDescription TagDescription; + +static TagDescription tag_descriptions[] = { + {'p', N_("Performer/Artist")}, + {'a', N_("Album")}, + {'g', N_("Genre")}, + {'f', N_("File name")}, + {'F', N_("File path")}, + {'e', N_("File extension")}, + {'t', N_("Track name")}, + {'n', N_("Track number")}, + {'d', N_("Date")}, + {'y', N_("Year")}, + {'c', N_("Comment")} +}; + +gint tag_descriptions_length = + sizeof(tag_descriptions) / sizeof(TagDescription); + +GtkWidget * +xmms_titlestring_descriptions(gchar * tags, gint columns) +{ + GtkWidget *table, *label; + gchar tag_str[5]; + gint num = strlen(tags); + gint r = 0, c, i; + + g_return_val_if_fail(tags != NULL, NULL); + g_return_val_if_fail(columns <= num, NULL); + + table = gtk_table_new((num + columns - 1) / columns, columns * 2, FALSE); + gtk_table_set_row_spacings(GTK_TABLE(table), 2); + gtk_table_set_col_spacings(GTK_TABLE(table), 5); + + for (c = 0; c < columns; c++) { + for (r = 0; r < (num + columns - 1 - c) / columns; r++) { + g_snprintf(tag_str, sizeof(tag_str), "%%%c:", *tags); + label = gtk_label_new(tag_str); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 2 * c, 2 * c + 1, r, + r + 1, GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show(label); + + for (i = 0; i < tag_descriptions_length; i++) { + if (*tags == tag_descriptions[i].tag) { + label = gtk_label_new(_(tag_descriptions[i].description)); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 2 * c + 1, + 2 * c + 2, r, r + 1, + GTK_EXPAND | GTK_FILL, + GTK_EXPAND | GTK_FILL, 0, 0); + gtk_widget_show(label); + break; + } + } + + if (i == tag_descriptions_length) + g_warning("Invalid tag: %c", *tags); + + tags++; + } + + } + + label = gtk_label_new(_("%{n:...%}: Display \"...\" only if element " + "%n is present")); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 0, r + 1, + r + 1, r + 2, GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show(label); + + return table; +}