1 /* zzm.c  -- zzm file routines
2  * $Id: zzm.c,v 1.2 2005/05/28 03:17:46 bitman Exp $
3  * Copyright (C) 2000 Ryan Phillips <bitman@scn.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (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 02111-1307, USA.
18  */
19 
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23 
24 
25 #include "zzm.h"
26 #include "kevedit/kevedit.h"
27 #include "editbox.h"
28 #include "structures/svector.h"
29 
30 #include <stdlib.h>
31 #include <string.h>
32 #include <stdio.h>
33 #include <ctype.h>
34 
35 
zzmpullsong(stringvector * zzmv,int songnum)36 stringvector zzmpullsong(stringvector * zzmv, int songnum)
37 {
38 	stringvector songlines;		/* List of zzm format music */
39 	stringnode * curline;		/* Current node */
40 
41 	initstringvector(&songlines);
42 
43 	if (songnum < 1)
44 		return songlines;
45 
46 	for (curline = zzmv->first; curline != NULL; curline = curline->next) {
47 		if (curline->s != NULL &&
48 		    str_equ(curline->s, "; $SONG ", STREQU_UNCASE | STREQU_FRONT)) {
49 			int cursongnum = 0;
50 			sscanf(curline->s + 8, "%d", &cursongnum);
51 			if (cursongnum == songnum)
52 				for (curline = curline->next; curline != NULL && curline->s[0] != ';'; curline = curline->next)
53 					pushstring(&songlines, strcpy((char *) malloc(strlen(curline->s)+2), curline->s));
54 		}
55 	}
56 
57 	return songlines;
58 }
59 
zzmpicksong(stringvector * zzmv,displaymethod * d)60 int zzmpicksong(stringvector * zzmv, displaymethod * d)
61 {
62 	stringvector songtitles;	/* List of song names in zzmv */
63 	stringvector rawtitles;		/* vector sharing strings with zzmv */
64 	stringnode * curline;		/* Current node */
65 	char *newstr;			/* New strings for songtitles */
66 	int i = 0, k = 0;
67 
68 	if (zzmv == NULL || zzmv->first == NULL)
69 		return -1;
70 
71 	initstringvector(&songtitles);
72 	initstringvector(&rawtitles);
73 
74 
75 	pushstring(&songtitles, strcpy((char *) malloc(42), "@here"));
76 	/* put header info at top of songtitles */
77 	for (curline = zzmv->first; curline != NULL; curline = curline->next) {
78 		if (curline->s != NULL &&
79 		    str_equ(curline->s, "; $TITLE ", STREQU_UNCASE | STREQU_FRONT)) {
80 			newstr = (char *) malloc(43);
81 			strcpy(newstr, "$");
82 			strncat(newstr, curline->s + 9, 41);
83 			for (i = 0; i < strlen(newstr); i++)
84 				if (newstr[i] == '~')
85 					newstr[i] = ' ';
86 
87 			pushstring(&songtitles, newstr);
88 			pushstring(&songtitles, strcpy((char *) malloc(2), ""));
89 		}
90 	}
91 
92 	/* find all the song titles and put them songnames */
93 	for (curline = zzmv->first; curline != NULL; curline = curline->next) {
94 		if (curline->s != NULL &&
95 		    str_equ(curline->s, "; $SONG TITLE ", STREQU_UNCASE | STREQU_FRONT)) {
96 
97 			/* put the song number and title in rawtitles */
98 			pushstring(&rawtitles, curline->s + 14);
99 		}
100 	}
101 
102 	if (rawtitles.first == NULL)
103 		return -1;
104 
105 	/* Sort rawtitles */
106 	/* Use insertion sort because the titles are most likely in order anyway. */
107 	if (rawtitles.first != NULL && rawtitles.first->next != NULL) {
108 		char *curstr = NULL;
109 		stringnode *nodepos = NULL;
110 		int valcur, valprev;
111 
112 		for (rawtitles.cur = rawtitles.first->next; rawtitles.cur != NULL; rawtitles.cur = rawtitles.cur->next) {
113 			curstr = rawtitles.cur->s;
114 			sscanf(rawtitles.cur->s, "%d", &valcur);
115 
116 			/* Find place to insert curstr */
117 			nodepos = rawtitles.cur;
118 			while (nodepos != rawtitles.first && (sscanf(nodepos->prev->s, "%d", &valprev), valprev) > valcur) {
119 				nodepos->s = nodepos->prev->s;
120 				nodepos = nodepos->prev;
121 			}
122 			nodepos->s = curstr;
123 		}
124 	}
125 
126 	/* Copy titles into songtitles for browsing */
127 
128 	for (rawtitles.cur = rawtitles.first; rawtitles.cur != NULL; rawtitles.cur = rawtitles.cur->next) {
129 		/* the title from rawtitles.cur can now be pushed onto songtitles */
130 		newstr = (char *) malloc(strlen(rawtitles.cur->s) + 3);
131 		strcpy(newstr, "!");
132 		strcat(newstr, rawtitles.cur->s);
133 		if (strstr(newstr, " ") != NULL)
134 			*strstr(newstr, " ") = ';';
135 
136 		/* remove ~s from older files */
137 		for (k = 0; k < strlen(newstr); k++)
138 			if (newstr[k] == '~') newstr[k] = ' ';
139 
140 		/* Cut the string off if wider than dialog */
141 		if (strlen(newstr) > 42)
142 			newstr[42] = 0;
143 
144 		pushstring(&songtitles, newstr);
145 	}
146 
147 	/* songtitles now contains all the info we need to offer a dialog */
148 	songtitles.cur = songtitles.first;
149 	do {
150 		if (editbox("Pick a ZZM Song", &songtitles, 0, 1, d) == 27) {
151 			deletestringvector(&songtitles);
152 			return -1;
153 		}
154 	} while (songtitles.cur->s[0] != '!');
155 
156 	/* determine the number chosen */
157 	sscanf(songtitles.cur->s, "%*c%d", &i);
158 
159 	deletestringvector(&songtitles);
160 
161 	return i;
162 }
163 
zzmripsong(stringvector * zoc,int maxseparation)164 stringvector zzmripsong(stringvector * zoc, int maxseparation)
165 {
166 	stringvector songlines;
167 	stringnode * curline = zoc->cur;
168 	int separation = 0;
169 
170 	initstringvector(&songlines);
171 
172 	while (curline != NULL && separation <= maxseparation) {
173 		char* tune = strstr(curline->s, "#");
174 		if (tune != NULL && str_equ(tune, "#play ", STREQU_UNCASE | STREQU_RFRONT)) {
175 			separation = 0;  /* Reset separation counter */
176 			tune += 6;       /* Advance to notes! */
177 
178 			/* Push the remainder of the line into songlines */
179 			pushstring(&songlines, str_dup(tune));
180 		} else {
181 			separation++;
182 		}
183 
184 		curline = curline->next;
185 	}
186 
187 	return songlines;
188 }
189