+static PICS_HEAD *
+parse_xpm(char **data)
+{
+ int state = 0;
+ PICS_HEAD *result = typeCalloc(PICS_HEAD, 1);
+ int n;
+ int cells = 0;
+ int color = 0;
+ int cpp = 1; /* chars per pixel */
+ int num[6];
+ int which = 0;
+ char ch;
+ const char *cs;
+ char *s;
+ char buf[BUFSIZ];
+ char arg1[BUFSIZ];
+ char arg2[BUFSIZ];
+ char arg3[BUFSIZ];
+ char **list = 0;
+
+ for (n = 0; data[n] != 0; ++n) {
+ if (strlen(s = data[n]) >= sizeof(buf) - 1)
+ continue;
+ switch (state) {
+ case 0:
+ if (match_c(s, " /* XPM */ ")) {
+ state = 1;
+ }
+ break;
+ case 1:
+ if (match_c(s, " static char * %s [] = %c ", arg1, &ch) &&
+ ch == L_CURL) {
+ result->name = strdup(arg1);
+ state = 2;
+ }
+ break;
+ case 2:
+ if (match_c(s, " \" %d %d %d %d \" , ",
+ num + 0, num + 1, num + 2, num + 3) ||
+ match_c(s, " \" %d %d %d %d %d %d \" , ",
+ num + 0, num + 1, num + 2, num + 3, num + 4, num + 5)) {
+ result->wide = num[0];
+ result->high = num[1];
+ result->colors = num[2];
+ result->pairs = typeCalloc(PICS_PAIR, result->colors);
+ cells = (size_t) (result->wide * result->high);
+ result->cells = typeCalloc(PICS_CELL, cells);
+ list = typeCalloc(char *, result->colors);
+ cpp = num[3];
+ state = 3;
+ }
+ break;
+ case 3:
+ if (match_c(s, " \" %s %s %s \" , ", arg1, arg2, arg3)) {
+ ;
+ } else if (match_c(s, " \" %s %s \" , ", arg2, arg3)) {
+ strcpy(arg1, " ");
+ } else {
+ break;
+ }
+ while ((int) strlen(arg1) < cpp)
+ strcat(arg1, " ");
+ list[color] = strdup(arg1);
+ if (!strcmp(arg3, "None")) {
+ result->pairs[color].fg = -1;
+ } else if (*arg3 == '#') {
+ unsigned long value = strtoul(arg3 + 1, &s, 16);
+ result->pairs[color].fg = (int) value;
+ } else {
+ result->pairs[color].fg = 0; /* actually an error */
+ }
+ if (++color >= result->colors)
+ state = 4;
+ break;
+ case 4:
+ if (*(cs = skip_s(s)) == '"') {
+ ++cs;
+ while (*cs != '\0' && *cs != '"') {
+ int c;
+
+ for (c = 0; c < result->colors; ++c) {
+ if (!strncmp(cs, list[c], cpp)) {
+ result->cells[which].ch = list[c][0];
+ result->cells[which].fg = c;
+ break;
+ }
+ }
+
+ if (result->cells[which].ch == 0) {
+ result->cells[which].ch = '?';
+ result->cells[which].fg = 0;
+ }
+
+ if (++which >= cells) {
+ state = 5;
+ break;
+ }
+ for (c = cpp; c > 0; --c, ++cs) ;
+ }
+ }
+ break;
+ }
+ }
+
+ if (result && list) {
+ for (n = 0; n < result->colors; ++n)
+ free(list[n]);
+ free(list);
+ }
+
+ if (state < 5) {
+ free_pics_head(result);
+ result = 0;
+ }
+
+ return result;
+}
+
+static PICS_HEAD *
+read_picture(const char *filename, char **data)
+{
+ PICS_HEAD *pics;
+ if ((pics = parse_xbm(data)) == 0) {
+ if ((pics = parse_xpm(data)) == 0) {
+ free_data(data);
+ giveup("unexpected file-format for \"%s\"", filename);
+ }
+ }
+ return pics;
+}
+