1 /************************************************************************
2 ************************************************************************
4 Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
5 ---------------------------------------------------------------------
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 ************************************************************************
20 ************************************************************************/
28 static Tree
makeSubFolderChain(Tree path
, Tree elem
);
29 static Tree
putFolder(Tree folder
, Tree item
);
30 static Tree
getFolder (Tree folder
, Tree ilabel
);
33 static void error(const char * s
, Tree t
)
35 fprintf(stderr
, "ERROR : %s (%p)\n", s
, t
);
38 #define ERROR(s,t) error(s,t); exit(1)
41 //------------------------------------------------------------------------------
43 //------------------------------------------------------------------------------
46 // version normale, qui marche, mais qui ne range pas en ordre alphabetique
47 static bool findKey (Tree pl
, Tree key
, Tree
& val
)
49 if (isNil(pl
)) return false;
50 if (left(hd(pl
)) == key
) { val
= right(hd(pl
)); return true; }
51 /* left(hd(pl)) != key */ return findKey (tl(pl
), key
, val
);
54 static Tree
updateKey (Tree pl
, Tree key
, Tree val
)
56 if (isNil(pl
)) return cons ( cons(key
,val
), nil
);
57 if (left(hd(pl
)) == key
) return cons ( cons(key
,val
), tl(pl
) );
58 /* left(hd(pl)) != key */ return cons ( hd(pl
), updateKey( tl(pl
), key
, val
));
61 static Tree
removeKey (Tree pl
, Tree key
)
63 if (isNil(pl
)) return nil
;
64 if (left(hd(pl
)) == key
) return tl(pl
);
65 /* left(hd(pl)) != key */ return cons (hd(pl
), removeKey(tl(pl
), key
));
70 // verion experimentale qui range en ordre alphabetique
72 static bool isBefore(Tree k1
, Tree k2
)
74 // before comparing replace (type . label) by label
75 if (isList(k1
)) { k1
= tl(k1
); }
76 if (isList(k2
)) { k2
= tl(k2
); }
78 //fprintf(stderr, "isBefore("); print(k1, stderr); fprintf(stderr,", "); print(k2, stderr); fprintf(stderr,")\n");
80 if (!isSym(k1
->node(), &s1
)) {
81 ERROR("the node of the tree is not a symbol", k1
);
83 if (!isSym(k2
->node(), &s2
)) {
84 ERROR("the node of the tree is not a symbol", k2
);
87 //fprintf (stderr, "strcmp(\"%s\", \"%s\") = %d\n", name(s1), name(s2), strcmp(name(s1), name(s2)));
88 return strcmp(name(s1
), name(s2
)) < 0;
92 static bool findKey (Tree pl
, Tree key
, Tree
& val
)
94 if (isNil(pl
)) return false;
95 if (left(hd(pl
)) == key
) { val
= right(hd(pl
)); return true; }
96 if (isBefore(left(hd(pl
)),key
)) return findKey (tl(pl
), key
, val
);
100 static Tree
updateKey (Tree pl
, Tree key
, Tree val
)
102 if (isNil(pl
)) return cons ( cons(key
,val
), nil
);
103 if (left(hd(pl
)) == key
) return cons ( cons(key
,val
), tl(pl
) );
104 if (isBefore(left(hd(pl
)),key
)) return cons ( hd(pl
), updateKey( tl(pl
), key
, val
));
105 return cons(cons(key
,val
), pl
);
109 * Like updateKey but allow multiple items with same key
111 static Tree
addKey (Tree pl
, Tree key
, Tree val
)
113 if (isNil(pl
)) return cons ( cons(key
,val
), nil
);
114 if (isBefore(key
, left(hd(pl
)))) return cons(cons(key
,val
), pl
);
115 return cons ( hd(pl
), addKey( tl(pl
), key
, val
));
120 static Tree
removeKey (Tree pl
, Tree key
)
122 if (isNil(pl
)) return nil
;
123 if (left(hd(pl
)) == key
) return tl(pl
);
124 if (isBefore(left(hd(pl
)),key
)) return cons (hd(pl
), removeKey(tl(pl
), key
));
130 //------------------------------------------------------------------------------
131 // gestion de la construction de l'arbre d'interface utilisateur
132 //------------------------------------------------------------------------------
134 Sym UIFOLDER
= symbol ("uiFolder");
135 Tree
uiFolder(Tree label
, Tree elements
) { return tree(UIFOLDER
, label
, elements
); }
136 bool isUiFolder(Tree t
) { return isTree(t
, UIFOLDER
); }
137 bool isUiFolder(Tree t
, Tree
& label
, Tree
& elements
) { return isTree(t
, UIFOLDER
, label
, elements
); }
139 Sym UIWIDGET
= symbol ("uiWidget");
140 Tree
uiWidget(Tree label
, Tree varname
, Tree sig
) { return tree(UIWIDGET
, label
, varname
, sig
); }
141 bool isUiWidget(Tree t
, Tree
& label
, Tree
& varname
, Tree
& sig
) { return isTree(t
, UIWIDGET
, label
, varname
, sig
); }
145 // place un item dans un folder. Remplace eventuellement l'élément de même nom.
146 Tree
putFolder(Tree folder
, Tree item
)
150 if ( ! isUiFolder(folder
, label
, content
)) { fprintf(stderr
, "ERROR in addFolder : not a folder\n"); }
151 return uiFolder(label
, updateKey(content
, uiLabel(item
), item
));
154 // place un item dans un folder. Sans Remplacement
155 Tree
addToFolder(Tree folder
, Tree item
)
159 if ( ! isUiFolder(folder
, label
, content
)) { fprintf(stderr
, "ERROR in addFolder : not a folder\n"); }
160 return uiFolder(label
, addKey(content
, uiLabel(item
), item
));
163 // get an item from a folder (or return NIL)
164 Tree
getFolder (Tree folder
, Tree ilabel
)
166 Tree flabel
, content
, item
;
167 if (!isUiFolder(folder
, flabel
, content
)) { fprintf(stderr
, "ERROR in getFolder : not a folder\n"); }
168 if (findKey(content
, ilabel
, item
)) {
175 // crée une chaine de dossiers correspondant à path et contenant in fine elem
176 Tree
makeSubFolderChain(Tree path
, Tree elem
)
181 return putFolder(uiFolder(hd(path
)), makeSubFolderChain(tl(path
),elem
));
186 Tree
putSubFolder(Tree folder
, Tree path
, Tree item
)
189 //return putFolder(folder, item);
190 return addToFolder(folder
, item
);
192 Tree subfolder
= getFolder(folder
, hd(path
));
193 if (isUiFolder(subfolder
)) {
194 return putFolder(folder
, putSubFolder(subfolder
, tl(path
), item
));
196 return putFolder(folder
, makeSubFolderChain(path
, item
));
203 Fonctionnement des dossiers.
204 Dossier à 1 niveau : Un dossier contient une liste de choses reperées par un nom :
205 Dossier[(l1,d1)...(ln,dn)]
206 ou (lx,dx) est une chose dx repérée par un nom lx. On suppose les lx tous différents
208 On peut ajouter une chose à un dossier : Ajouter(Dossier, Chose) -> Dossier
210 Si le dossier contient deja qq chose de meme nom, cette chose est remplacée par la nouvelle.
212 AJOUTER (Dossier[(l1,d1)...(ln,dn)], (lx,dx)) -> Dossier[(l1,d1)...(lx,dx)...(ln,dn)]
214 AJOUTER (Dossier[(l1,d1)...(lx,dx)...(ln,dn)], (lx,dx')) -> Dossier[(l1,d1)...(lx,dx')...(ln,dn)]