RNA minor changes
[blender.git] / source / blender / makesrna / intern / rna_access.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
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.
15  *
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 Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * Contributor(s): Blender Foundation (2008).
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "MEM_guardedalloc.h"
29
30 #include "BLI_blenlib.h"
31 #include "BLI_dynstr.h"
32
33 #include "DNA_ID.h"
34
35 #include "RNA_access.h"
36 #include "RNA_types.h"
37
38 #include "rna_internal.h"
39
40 /* Pointer */
41
42 void RNA_pointer_main_get(struct Main *main, struct PointerRNA *r_ptr)
43 {
44         r_ptr->data= main;
45         r_ptr->type= &RNA_Main;
46         r_ptr->id.data= NULL;
47         r_ptr->id.type= NULL;
48 }
49
50 static void rna_pointer_inherit_id(PointerRNA *parent, PointerRNA *ptr)
51 {
52         if(ptr->type && ptr->type->flag & STRUCT_ID) {
53                 ptr->id.data= ptr->data;
54                 ptr->id.type= ptr->type;
55         }
56         else {
57                 ptr->id.data= parent->id.data;
58                 ptr->id.type= parent->id.type;
59         }
60 }
61
62 /* ID Properties */
63
64 IDProperty *rna_idproperty_check(PropertyRNA **prop, PointerRNA *ptr)
65 {
66         /* This is quite a hack, but avoids some complexity in the API. we
67          * pass IDProperty structs as PropertyRNA pointers to the outside.
68          * We store some bytes in PropertyRNA structs that allows us to
69          * distinguish it from IDProperty structs. If it is an ID property,
70          * we look up an IDP PropertyRNA based on the type, and set the data
71          * pointer to the IDProperty. */
72
73         /* these bytes have */
74         if((*prop)->magic == RNA_MAGIC) {
75                 return 0;
76         }
77         else {
78                 static PropertyRNA *typemap[IDP_NUMTYPES] =
79                         {(PropertyRNA*)&rna_IDProperty_string,
80                          (PropertyRNA*)&rna_IDProperty_int,
81                          (PropertyRNA*)&rna_IDProperty_float,
82                          NULL, NULL, NULL,
83                          (PropertyRNA*)&rna_IDProperty_group, NULL,
84                          (PropertyRNA*)&rna_IDProperty_double};
85
86                 static PropertyRNA *arraytypemap[IDP_NUMTYPES] =
87                         {NULL, (PropertyRNA*)&rna_IDProperty_intarray,
88                          (PropertyRNA*)&rna_IDProperty_floatarray,
89                          NULL, NULL, NULL, NULL, NULL,
90                          (PropertyRNA*)&rna_IDProperty_doublearray};
91
92                 IDProperty *idprop;
93
94                 idprop= (IDProperty*)*prop;
95                 if(idprop->type == IDP_ARRAY)
96                         *prop= arraytypemap[(int)(idprop->subtype)];
97                 else 
98                         *prop= typemap[(int)(idprop->type)];
99
100                 if(ptr)
101                         ptr->data= idprop;
102
103                 return idprop;
104         }
105 }
106
107 /* Structs */
108
109 const char *RNA_struct_identifier(PointerRNA *ptr)
110 {
111         return ptr->type->identifier;
112 }
113
114 const char *RNA_struct_ui_name(PointerRNA *ptr)
115 {
116         return ptr->type->name;
117 }
118
119 PropertyRNA *RNA_struct_name_property(PointerRNA *ptr)
120 {
121         return ptr->type->nameproperty;
122 }
123
124 PropertyRNA *RNA_struct_iterator_property(PointerRNA *ptr)
125 {
126         return ptr->type->iteratorproperty;
127 }
128
129 /* Property Information */
130
131 const char *RNA_property_identifier(PropertyRNA *prop, PointerRNA *ptr)
132 {
133         IDProperty *idprop;
134
135         if((idprop=rna_idproperty_check(&prop, NULL)))
136                 return idprop->name;
137         else
138                 return prop->identifier;
139 }
140
141 PropertyType RNA_property_type(PropertyRNA *prop, PointerRNA *ptr)
142 {
143         rna_idproperty_check(&prop, NULL);
144
145         return prop->type;
146 }
147
148 PropertySubType RNA_property_subtype(PropertyRNA *prop, PointerRNA *ptr)
149 {
150         rna_idproperty_check(&prop, NULL);
151
152         return prop->subtype;
153 }
154
155 int RNA_property_array_length(PropertyRNA *prop, PointerRNA *ptr)
156 {
157         IDProperty *idprop;
158
159         if((idprop=rna_idproperty_check(&prop, NULL)) && idprop->type==IDP_ARRAY)
160                 return idprop->len;
161         else
162                 return prop->arraylength;
163 }
164
165 void RNA_property_int_range(PropertyRNA *prop, PointerRNA *ptr, int *hardmin, int *hardmax)
166 {
167         IntPropertyRNA *iprop;
168         
169         rna_idproperty_check(&prop, NULL);
170         iprop= (IntPropertyRNA*)prop;
171
172         *hardmin= iprop->hardmin;
173         *hardmax= iprop->hardmax;
174 }
175
176 void RNA_property_int_ui_range(PropertyRNA *prop, PointerRNA *ptr, int *softmin, int *softmax, int *step)
177 {
178         IntPropertyRNA *iprop;
179         
180         rna_idproperty_check(&prop, NULL);
181         iprop= (IntPropertyRNA*)prop;
182
183         *softmin= iprop->softmin;
184         *softmax= iprop->softmax;
185         *step= iprop->step;
186 }
187
188 void RNA_property_float_range(PropertyRNA *prop, PointerRNA *ptr, float *hardmin, float *hardmax)
189 {
190         FloatPropertyRNA *fprop;
191
192         rna_idproperty_check(&prop, NULL);
193         fprop= (FloatPropertyRNA*)prop;
194
195         *hardmin= fprop->hardmin;
196         *hardmax= fprop->hardmax;
197 }
198
199 void RNA_property_float_ui_range(PropertyRNA *prop, PointerRNA *ptr, float *softmin, float *softmax, float *step, float *precision)
200 {
201         FloatPropertyRNA *fprop;
202
203         rna_idproperty_check(&prop, NULL);
204         fprop= (FloatPropertyRNA*)prop;
205
206         *softmin= fprop->softmin;
207         *softmax= fprop->softmax;
208         *step= fprop->step;
209         *precision= fprop->precision;
210 }
211
212 int RNA_property_string_maxlength(PropertyRNA *prop, PointerRNA *ptr)
213 {
214         StringPropertyRNA *sprop;
215         
216         rna_idproperty_check(&prop, NULL);
217         sprop= (StringPropertyRNA*)prop;
218
219         return sprop->maxlength;
220 }
221
222 void RNA_property_enum_items(PropertyRNA *prop, PointerRNA *ptr, const EnumPropertyItem **item, int *totitem)
223 {
224         EnumPropertyRNA *eprop;
225
226         rna_idproperty_check(&prop, NULL);
227         eprop= (EnumPropertyRNA*)prop;
228
229         *item= eprop->item;
230         *totitem= eprop->totitem;
231 }
232
233 const char *RNA_property_ui_name(PropertyRNA *prop, PointerRNA *ptr)
234 {
235         IDProperty *idprop;
236
237         if((idprop=rna_idproperty_check(&prop, NULL)))
238                 return idprop->name;
239         else
240                 return prop->name;
241 }
242
243 const char *RNA_property_ui_description(PropertyRNA *prop, PointerRNA *ptr)
244 {
245         if(rna_idproperty_check(&prop, NULL))
246                 return "";
247         else
248                 return prop->description;
249 }
250
251 int RNA_property_editable(PropertyRNA *prop, PointerRNA *ptr)
252 {
253         rna_idproperty_check(&prop, NULL);
254
255         return !(prop->flag & PROP_NOT_EDITABLE);
256 }
257
258 int RNA_property_evaluated(PropertyRNA *prop, PointerRNA *ptr)
259 {
260         rna_idproperty_check(&prop, NULL);
261
262         return (prop->flag & PROP_EVALUATED);
263 }
264
265 void RNA_property_notify(PropertyRNA *prop, struct bContext *C, PointerRNA *ptr)
266 {
267         rna_idproperty_check(&prop, NULL);
268
269         if(prop->notify)
270                 prop->notify(C, ptr);
271 }
272
273 /* Property Data */
274
275 int RNA_property_boolean_get(PropertyRNA *prop, PointerRNA *ptr)
276 {
277         BooleanPropertyRNA *bprop;
278
279         rna_idproperty_check(&prop, ptr);
280         bprop= (BooleanPropertyRNA*)prop;
281
282         return bprop->get(ptr);
283 }
284
285 void RNA_property_boolean_set(PropertyRNA *prop, PointerRNA *ptr, int value)
286 {
287         BooleanPropertyRNA *bprop;
288
289         rna_idproperty_check(&prop, ptr);
290         bprop= (BooleanPropertyRNA*)prop;
291
292         if(bprop->set)
293                 bprop->set(ptr, value);
294 }
295
296 int RNA_property_boolean_get_array(PropertyRNA *prop, PointerRNA *ptr, int index)
297 {
298         BooleanPropertyRNA *bprop;
299
300         rna_idproperty_check(&prop, ptr);
301         bprop= (BooleanPropertyRNA*)prop;
302
303         return bprop->getarray(ptr, index);
304 }
305
306 void RNA_property_boolean_set_array(PropertyRNA *prop, PointerRNA *ptr, int index, int value)
307 {
308         BooleanPropertyRNA *bprop;
309
310         rna_idproperty_check(&prop, ptr);
311         bprop= (BooleanPropertyRNA*)prop;
312
313         if(bprop->setarray)
314                 bprop->setarray(ptr, index, value);
315 }
316
317 int RNA_property_int_get(PropertyRNA *prop, PointerRNA *ptr)
318 {
319         IntPropertyRNA *iprop;
320
321         rna_idproperty_check(&prop, ptr);
322         iprop= (IntPropertyRNA*)prop;
323
324         return iprop->get(ptr);
325 }
326
327 void RNA_property_int_set(PropertyRNA *prop, PointerRNA *ptr, int value)
328 {
329         IntPropertyRNA *iprop;
330
331         rna_idproperty_check(&prop, ptr);
332         iprop= (IntPropertyRNA*)prop;
333
334         if(iprop->set)
335                 iprop->set(ptr, value);
336 }
337
338 int RNA_property_int_get_array(PropertyRNA *prop, PointerRNA *ptr, int index)
339 {
340         IntPropertyRNA *iprop;
341
342         rna_idproperty_check(&prop, ptr);
343         iprop= (IntPropertyRNA*)prop;
344
345         return iprop->getarray(ptr, index);
346 }
347
348 void RNA_property_int_set_array(PropertyRNA *prop, PointerRNA *ptr, int index, int value)
349 {
350         IntPropertyRNA *iprop;
351
352         rna_idproperty_check(&prop, ptr);
353         iprop= (IntPropertyRNA*)prop;
354
355         if(iprop->setarray)
356                 iprop->setarray(ptr, index, value);
357 }
358
359 float RNA_property_float_get(PropertyRNA *prop, PointerRNA *ptr)
360 {
361         FloatPropertyRNA *fprop;
362
363         rna_idproperty_check(&prop, ptr);
364         fprop= (FloatPropertyRNA*)prop;
365
366         return fprop->get(ptr);
367 }
368
369 void RNA_property_float_set(PropertyRNA *prop, PointerRNA *ptr, float value)
370 {
371         FloatPropertyRNA *fprop;
372
373         rna_idproperty_check(&prop, ptr);
374         fprop= (FloatPropertyRNA*)prop;
375
376         if(fprop->set)
377                 fprop->set(ptr, value);
378 }
379
380 float RNA_property_float_get_array(PropertyRNA *prop, PointerRNA *ptr, int index)
381 {
382         FloatPropertyRNA *fprop;
383
384         rna_idproperty_check(&prop, ptr);
385         fprop= (FloatPropertyRNA*)prop;
386
387         return fprop->getarray(ptr, index);
388 }
389
390 void RNA_property_float_set_array(PropertyRNA *prop, PointerRNA *ptr, int index, float value)
391 {
392         FloatPropertyRNA *fprop;
393
394         rna_idproperty_check(&prop, ptr);
395         fprop= (FloatPropertyRNA*)prop;
396
397         if(fprop->setarray)
398                 fprop->setarray(ptr, index, value);
399 }
400
401 void RNA_property_string_get(PropertyRNA *prop, PointerRNA *ptr, char *value)
402 {
403         StringPropertyRNA *sprop;
404
405         rna_idproperty_check(&prop, ptr);
406         sprop= (StringPropertyRNA*)prop;
407
408         sprop->get(ptr, value);
409 }
410
411 char *RNA_property_string_get_alloc(PropertyRNA *prop, PointerRNA *ptr, char *fixedbuf, int fixedlen)
412 {
413         char *buf;
414         int length;
415
416         rna_idproperty_check(&prop, ptr);
417
418         length= RNA_property_string_length(prop, ptr);
419
420         if(length+1 < fixedlen)
421                 buf= fixedbuf;
422         else
423                 buf= MEM_callocN(sizeof(char)*(length+1), "RNA_string_get_alloc");
424
425         RNA_property_string_get(prop, ptr, buf);
426
427         return buf;
428 }
429
430 int RNA_property_string_length(PropertyRNA *prop, PointerRNA *ptr)
431 {
432         StringPropertyRNA *sprop;
433
434         rna_idproperty_check(&prop, ptr);
435         sprop= (StringPropertyRNA*)prop;
436
437         return sprop->length(ptr);
438 }
439
440 void RNA_property_string_set(PropertyRNA *prop, PointerRNA *ptr, const char *value)
441 {
442         StringPropertyRNA *sprop;
443
444         rna_idproperty_check(&prop, ptr);
445         sprop= (StringPropertyRNA*)prop;
446
447         if(sprop->set)
448                 sprop->set(ptr, value);
449 }
450
451 int RNA_property_enum_get(PropertyRNA *prop, PointerRNA *ptr)
452 {
453         EnumPropertyRNA *eprop;
454
455         rna_idproperty_check(&prop, ptr);
456         eprop= (EnumPropertyRNA*)prop;
457
458         return eprop->get(ptr);
459 }
460
461 void RNA_property_enum_set(PropertyRNA *prop, PointerRNA *ptr, int value)
462 {
463         EnumPropertyRNA *eprop;
464
465         rna_idproperty_check(&prop, ptr);
466         eprop= (EnumPropertyRNA*)prop;
467
468         if(eprop->set)
469                 eprop->set(ptr, value);
470 }
471
472 void RNA_property_pointer_get(PropertyRNA *prop, PointerRNA *ptr, PointerRNA *r_ptr)
473 {
474         PointerPropertyRNA *pprop;
475
476         rna_idproperty_check(&prop, ptr);
477         pprop= (PointerPropertyRNA*)prop;
478
479         r_ptr->data= pprop->get(ptr);
480
481         if(r_ptr->data && (r_ptr->type= RNA_property_pointer_type(prop, ptr)))
482                 rna_pointer_inherit_id(ptr, r_ptr);
483         else
484                 memset(r_ptr, 0, sizeof(*r_ptr));
485 }
486
487 void RNA_property_pointer_set(PropertyRNA *prop, PointerRNA *ptr, PointerRNA *ptr_value)
488 {
489         PointerPropertyRNA *pprop;
490
491         rna_idproperty_check(&prop, ptr);
492         pprop= (PointerPropertyRNA*)prop;
493
494         if(pprop->set)
495                 pprop->set(ptr, ptr_value->data);
496 }
497
498 StructRNA *RNA_property_pointer_type(PropertyRNA *prop, PointerRNA *ptr)
499 {
500         PointerPropertyRNA *pprop;
501
502         rna_idproperty_check(&prop, ptr);
503         pprop= (PointerPropertyRNA*)prop;
504
505         if(pprop->type)
506                 return pprop->type(ptr);
507         
508         return pprop->structtype;
509 }
510
511 static StructRNA *rna_property_collection_type(PropertyRNA *prop, CollectionPropertyIterator *iter)
512 {
513         CollectionPropertyRNA *cprop;
514
515         rna_idproperty_check(&prop, NULL);
516         cprop= (CollectionPropertyRNA*)prop;
517
518         if(cprop->type)
519                 return cprop->type(iter);
520         
521         return cprop->structtype;
522 }
523
524 static void rna_property_collection_get(PropertyRNA *prop, CollectionPropertyIterator *iter, PointerRNA *r_ptr)
525 {
526         CollectionPropertyRNA *cprop;
527
528         rna_idproperty_check(&prop, NULL);
529         cprop= (CollectionPropertyRNA*)prop;
530
531         r_ptr->data= cprop->get(iter);
532
533         if(r_ptr->data && (r_ptr->type= rna_property_collection_type(prop, iter)))
534                 rna_pointer_inherit_id(&iter->parent, r_ptr);
535         else
536                 memset(r_ptr, 0, sizeof(*r_ptr));
537 }
538
539 void RNA_property_collection_begin(PropertyRNA *prop, CollectionPropertyIterator *iter, PointerRNA *ptr)
540 {
541         CollectionPropertyRNA *cprop;
542
543         rna_idproperty_check(&prop, ptr);
544         cprop= (CollectionPropertyRNA*)prop;
545
546         iter->parent= *ptr;
547         cprop->begin(iter, ptr);
548
549         if(iter->valid)
550                 rna_property_collection_get(prop, iter, &iter->ptr);
551         else
552                 memset(&iter->ptr, 0, sizeof(iter->ptr));
553 }
554
555 void RNA_property_collection_next(PropertyRNA *prop, CollectionPropertyIterator *iter)
556 {
557         CollectionPropertyRNA *cprop;
558
559         rna_idproperty_check(&prop, NULL);
560         cprop= (CollectionPropertyRNA*)prop;
561
562         cprop->next(iter);
563
564         if(iter->valid)
565                 rna_property_collection_get(prop, iter, &iter->ptr);
566         else
567                 memset(&iter->ptr, 0, sizeof(iter->ptr));
568 }
569
570 void RNA_property_collection_end(PropertyRNA *prop, CollectionPropertyIterator *iter)
571 {
572         CollectionPropertyRNA *cprop;
573
574         rna_idproperty_check(&prop, NULL);
575         cprop= (CollectionPropertyRNA*)prop;
576
577         if(cprop->end)
578                 cprop->end(iter);
579 }
580
581 int RNA_property_collection_length(PropertyRNA *prop, PointerRNA *ptr)
582 {
583         CollectionPropertyRNA *cprop;
584
585         rna_idproperty_check(&prop, ptr);
586         cprop= (CollectionPropertyRNA*)prop;
587
588         if(cprop->length) {
589                 return cprop->length(ptr);
590         }
591         else {
592                 CollectionPropertyIterator iter;
593                 int length= 0;
594
595                 RNA_property_collection_begin(prop, &iter, ptr);
596                 for(; iter.valid; RNA_property_collection_next(prop, &iter))
597                         length++;
598                 RNA_property_collection_end(prop, &iter);
599
600                 return length;
601         }
602 }
603
604 int RNA_property_collection_lookup_int(PropertyRNA *prop, PointerRNA *ptr, int key, PointerRNA *r_ptr)
605 {
606         CollectionPropertyRNA *cprop;
607
608         rna_idproperty_check(&prop, ptr);
609         cprop= (CollectionPropertyRNA*)prop;
610
611         if(cprop->lookupint) {
612                 /* we have a callback defined, use it */
613                 r_ptr->data= cprop->lookupint(ptr, key, &r_ptr->type);
614
615                 if(r_ptr->data) {
616                         if(!r_ptr->type)
617                                 r_ptr->type= cprop->structtype;
618                         rna_pointer_inherit_id(ptr, r_ptr);
619
620                         return 1;
621                 }
622                 else {
623                         memset(r_ptr, 0, sizeof(*r_ptr));
624                         return 0;
625                 }
626         }
627         else {
628                 /* no callback defined, just iterate and find the nth item */
629                 CollectionPropertyIterator iter;
630                 int i;
631
632                 RNA_property_collection_begin(prop, &iter, ptr);
633                 for(i=0; iter.valid; RNA_property_collection_next(prop, &iter), i++) {
634                         if(i == key) {
635                                 *r_ptr= iter.ptr;
636                                 break;
637                         }
638                 }
639                 RNA_property_collection_end(prop, &iter);
640
641                 if(!iter.valid)
642                         memset(r_ptr, 0, sizeof(*r_ptr));
643
644                 return iter.valid;
645         }
646 }
647
648 int RNA_property_collection_lookup_string(PropertyRNA *prop, PointerRNA *ptr, const char *key, PointerRNA *r_ptr)
649 {
650         CollectionPropertyRNA *cprop;
651
652         rna_idproperty_check(&prop, ptr);
653         cprop= (CollectionPropertyRNA*)prop;
654
655         if(cprop->lookupstring) {
656                 /* we have a callback defined, use it */
657                 r_ptr->data= cprop->lookupstring(ptr, key, &r_ptr->type);
658
659                 if(r_ptr->data) {
660                         if(!r_ptr->type)
661                                 r_ptr->type= cprop->structtype;
662                         rna_pointer_inherit_id(ptr, r_ptr);
663
664                         return 1;
665                 }
666                 else {
667                         memset(r_ptr, 0, sizeof(*r_ptr));
668                         return 0;
669                 }
670         }
671         else {
672                 /* no callback defined, compare with name properties if they exist */
673                 CollectionPropertyIterator iter;
674                 PropertyRNA *nameprop;
675                 char name[256], *nameptr;
676                 int length, alloc, found= 0;
677
678                 RNA_property_collection_begin(prop, &iter, ptr);
679                 for(; iter.valid; RNA_property_collection_next(prop, &iter)) {
680                         if(iter.ptr.data && iter.ptr.type->nameproperty) {
681                                 nameprop= iter.ptr.type->nameproperty;
682
683                                 length= RNA_property_string_length(nameprop, &iter.ptr);
684
685                                 if(sizeof(name)-1 < length) {
686                                         nameptr= name;
687                                         alloc= 0;
688                                 }
689                                 else {
690                                         nameptr= MEM_mallocN(sizeof(char)*length+1, "RNA_lookup_string");
691                                         alloc= 1;
692                                 }
693
694                                 RNA_property_string_get(nameprop, &iter.ptr, nameptr);
695
696                                 if(strcmp(nameptr, key) == 0) {
697                                         *r_ptr= iter.ptr;
698                                         found= 1;
699                                 }
700
701                                 if(alloc)
702                                         MEM_freeN(nameptr);
703
704                                 if(found)
705                                         break;
706                         }
707                 }
708                 RNA_property_collection_end(prop, &iter);
709
710                 if(!iter.valid)
711                         memset(r_ptr, 0, sizeof(*r_ptr));
712
713                 return iter.valid;
714         }
715 }
716
717 /* Standard iterator functions */
718
719 void rna_iterator_listbase_begin(CollectionPropertyIterator *iter, ListBase *lb)
720 {
721         ListBaseIterator *internal;
722
723         internal= MEM_callocN(sizeof(ListBaseIterator), "ListBaseIterator");
724         internal->link= lb->first;
725
726         iter->internal= internal;
727         iter->valid= (internal->link != NULL);
728 }
729
730 void rna_iterator_listbase_next(CollectionPropertyIterator *iter)
731 {
732         ListBaseIterator *internal= iter->internal;
733
734         internal->link= internal->link->next;
735         iter->valid= (internal->link != NULL);
736 }
737
738 void *rna_iterator_listbase_get(CollectionPropertyIterator *iter)
739 {
740         ListBaseIterator *internal= iter->internal;
741
742         return internal->link;
743 }
744
745 void rna_iterator_listbase_end(CollectionPropertyIterator *iter)
746 {
747         MEM_freeN(iter->internal);
748 }
749
750 void rna_iterator_array_begin(CollectionPropertyIterator *iter, void *ptr, int itemsize, int length)
751 {
752         ArrayIterator *internal;
753
754         internal= MEM_callocN(sizeof(ArrayIterator), "ArrayIterator");
755         internal->ptr= ptr;
756         internal->endptr= ((char*)ptr)+length*itemsize;
757         internal->itemsize= itemsize;
758
759         iter->internal= internal;
760         iter->valid= (internal->ptr != internal->endptr);
761 }
762
763 void rna_iterator_array_next(CollectionPropertyIterator *iter)
764 {
765         ArrayIterator *internal= iter->internal;
766
767         internal->ptr += internal->itemsize;
768         iter->valid= (internal->ptr != internal->endptr);
769 }
770
771 void *rna_iterator_array_get(CollectionPropertyIterator *iter)
772 {
773         ArrayIterator *internal= iter->internal;
774
775         return internal->ptr;
776 }
777
778 void rna_iterator_array_end(CollectionPropertyIterator *iter)
779 {
780         MEM_freeN(iter->internal);
781 }
782
783 /* RNA Path - Experiment */
784
785 static char *rna_path_token(const char **path, char *fixedbuf, int fixedlen, int bracket)
786 {
787         const char *p;
788         char *buf;
789         int i, j, len, escape;
790
791         len= 0;
792
793         if(bracket) {
794                 /* get data between [], check escaping ] with \] */
795                 if(**path == '[') (*path)++;
796                 else return NULL;
797
798                 p= *path;
799
800                 escape= 0;
801                 while(*p && (*p != ']' || escape)) {
802                         escape= (*p == '\\');
803                         len++;
804                         p++;
805                 }
806
807                 if(*p != ']') return NULL;
808         }
809         else {
810                 /* get data until . or [ */
811                 p= *path;
812
813                 while(*p && *p != '.' && *p != '[') {
814                         len++;
815                         p++;
816                 }
817         }
818         
819         /* empty, return */
820         if(len == 0)
821                 return NULL;
822         
823         /* try to use fixed buffer if possible */
824         if(len+1 < fixedlen)
825                 buf= fixedbuf;
826         else
827                 buf= MEM_callocN(sizeof(char)*(len+1), "rna_path_token");
828
829         /* copy string, taking into account escaped ] */
830         for(p=*path, i=0, j=0; i<len; i++, p++) {
831                 if(*p == '\\' && *(p+1) == ']');
832                 else buf[j++]= *p;
833         }
834
835         buf[j]= 0;
836
837         /* set path to start of next token */
838         if(*p == ']') p++;
839         if(*p == '.') p++;
840         *path= p;
841
842         return buf;
843 }
844
845 int RNA_path_resolve(PointerRNA *ptr, const char *path, PointerRNA *r_ptr, PropertyRNA **r_prop)
846 {
847         CollectionPropertyIterator iter;
848         PropertyRNA *prop, *iterprop;
849         PointerRNA curptr, nextptr;
850         char fixedbuf[256], *token;
851         int len, intkey;
852
853         prop= NULL;
854         curptr= *ptr;
855
856         while(*path) {
857                 /* look up property name in current struct */
858                 token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 0);
859
860                 if(!token)
861                         return 0;
862
863                 iterprop= RNA_struct_iterator_property(&curptr);
864                 RNA_property_collection_begin(iterprop, &iter, &curptr);
865                 prop= NULL;
866
867                 for(; iter.valid; RNA_property_collection_next(iterprop, &iter)) {
868                         if(strcmp(token, RNA_property_identifier(iter.ptr.data, &iter.ptr)) == 0) {
869                                 prop= iter.ptr.data;
870                                 break;
871                         }
872                 }
873
874                 RNA_property_collection_end(iterprop, &iter);
875
876                 if(token != fixedbuf)
877                         MEM_freeN(token);
878
879                 if(!prop)
880                         return 0;
881
882                 /* now look up the value of this property if it is a pointer or
883                  * collection, otherwise return the property rna so that the
884                  * caller can read the value of the property itself */
885                 if(RNA_property_type(prop, &curptr) == PROP_POINTER) {
886                         RNA_property_pointer_get(prop, &curptr, &nextptr);
887
888                         if(nextptr.data)
889                                 curptr= nextptr;
890                         else
891                                 return 0;
892                 }
893                 else if(RNA_property_type(prop, &curptr) == PROP_COLLECTION && *path) {
894                         /* resolve the lookup with [] brackets */
895                         token= rna_path_token(&path, fixedbuf, sizeof(fixedbuf), 1);
896
897                         if(!token)
898                                 return 0;
899
900                         len= strlen(token);
901
902                         /* check for "" to see if it is a string */
903                         if(len >= 2 && *token == '"' && token[len-2] == '"') {
904                                 /* strip away "" */
905                                 token[len-2]= 0;
906                                 RNA_property_collection_lookup_string(prop, &curptr, token+1, &nextptr);
907                         }
908                         else {
909                                 /* otherwise do int lookup */
910                                 intkey= atoi(token);
911                                 RNA_property_collection_lookup_int(prop, &curptr, intkey, &nextptr);
912                         }
913
914                         if(token != fixedbuf)
915                                 MEM_freeN(token);
916
917                         if(nextptr.data)
918                                 curptr= nextptr;
919                         else
920                                 return 0;
921                 }
922         }
923
924         *r_ptr= curptr;
925         *r_prop= prop;
926
927         return 1;
928 }
929
930 char *RNA_path_append(const char *path, PointerRNA *ptr, PropertyRNA *prop, int intkey, const char *strkey)
931 {
932         DynStr *dynstr;
933         const char *s;
934         char appendstr[128], *result;
935         
936         dynstr= BLI_dynstr_new();
937
938         /* add .identifier */
939         if(path) {
940                 BLI_dynstr_append(dynstr, (char*)path);
941                 if(*path)
942                         BLI_dynstr_append(dynstr, ".");
943         }
944
945         BLI_dynstr_append(dynstr, (char*)RNA_property_identifier(prop, ptr));
946
947         if(RNA_property_type(prop, ptr) == PROP_COLLECTION) {
948                 /* add ["strkey"] or [intkey] */
949                 BLI_dynstr_append(dynstr, "[");
950
951                 if(strkey) {
952                         BLI_dynstr_append(dynstr, "\"");
953                         for(s=strkey; *s; s++) {
954                                 if(*s == '[') {
955                                         appendstr[0]= '\\';
956                                         appendstr[1]= *s;
957                                         appendstr[2]= 0;
958                                 }
959                                 else {
960                                         appendstr[0]= *s;
961                                         appendstr[1]= 0;
962                                 }
963                                 BLI_dynstr_append(dynstr, appendstr);
964                         }
965                         BLI_dynstr_append(dynstr, "\"");
966                 }
967                 else {
968                         sprintf(appendstr, "%d", intkey);
969                         BLI_dynstr_append(dynstr, appendstr);
970                 }
971
972                 BLI_dynstr_append(dynstr, "]");
973         }
974
975         result= BLI_dynstr_get_cstring(dynstr);
976         BLI_dynstr_free(dynstr);
977
978         return result;
979 }
980
981 char *RNA_path_back(const char *path)
982 {
983         char fixedbuf[256];
984         const char *previous, *current;
985         char *result, *token;
986         int i;
987
988         if(!path)
989                 return NULL;
990
991         previous= NULL;
992         current= path;
993
994         /* parse token by token until the end, then we back up to the previous
995          * position and strip of the next token to get the path one step back */
996         while(*current) {
997                 token= rna_path_token(&current, fixedbuf, sizeof(fixedbuf), 0);
998
999                 if(!token)
1000                         return NULL;
1001                 if(token != fixedbuf)
1002                         MEM_freeN(token);
1003
1004                 /* in case of collection we also need to strip off [] */
1005                 token= rna_path_token(&current, fixedbuf, sizeof(fixedbuf), 1);
1006                 if(token && token != fixedbuf)
1007                         MEM_freeN(token);
1008                 
1009                 if(!*current)
1010                         break;
1011
1012                 previous= current;
1013         }
1014
1015         if(!previous)
1016                 return NULL;
1017
1018         /* copy and strip off last token */
1019         i= previous - path;
1020         result= BLI_strdup(path);
1021
1022         if(i > 0 && result[i-1] == '.') i--;
1023         result[i]= 0;
1024
1025         return result;
1026 }
1027