47b29b49689009f83194df9f449d6036eb6c194f
[blender.git] / source / blender / blenkernel / intern / context.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Contributor(s): Blender Foundation (2008).
19  *
20  * ***** END GPL LICENSE BLOCK *****
21  */
22
23 /** \file blender/blenkernel/intern/context.c
24  *  \ingroup bke
25  */
26
27 #include <string.h>
28 #include <stdlib.h>
29 #include <stddef.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "DNA_scene_types.h"
34 #include "DNA_screen_types.h"
35 #include "DNA_space_types.h"
36 #include "DNA_view3d_types.h"
37 #include "DNA_windowmanager_types.h"
38 #include "DNA_object_types.h"
39 #include "DNA_linestyle_types.h"
40
41 #include "BLI_listbase.h"
42 #include "BLI_string.h"
43 #include "BLI_threads.h"
44 #include "BLI_utildefines.h"
45
46 #include "BLF_translation.h"
47
48 #include "BKE_context.h"
49 #include "BKE_main.h"
50 #include "BKE_screen.h"
51 #include "BKE_freestyle.h"
52
53 #include "RNA_access.h"
54
55 #ifdef WITH_PYTHON
56 #  include "BPY_extern.h"
57 #endif
58
59 /* struct */
60
61 struct bContext {
62         int thread;
63
64         /* windowmanager context */
65         struct {
66                 struct wmWindowManager *manager;
67                 struct wmWindow *window;
68                 struct bScreen *screen;
69                 struct ScrArea *area;
70                 struct ARegion *region;
71                 struct ARegion *menu;
72                 struct bContextStore *store;
73                 const char *operator_poll_msg; /* reason for poll failing */
74         } wm;
75         
76         /* data context */
77         struct {
78                 struct Main *main;
79                 struct Scene *scene;
80
81                 int recursion;
82                 int py_init; /* true if python is initialized */
83                 void *py_context;
84         } data;
85         
86         /* data evaluation */
87 #if 0
88         struct {
89                 int render;
90         } eval;
91 #endif
92 };
93
94 /* context */
95
96 bContext *CTX_create(void)
97 {
98         bContext *C;
99         
100         C = MEM_callocN(sizeof(bContext), "bContext");
101
102         return C;
103 }
104
105 bContext *CTX_copy(const bContext *C)
106 {
107         bContext *newC = MEM_dupallocN((void *)C);
108
109         return newC;
110 }
111
112 void CTX_free(bContext *C)
113 {
114         MEM_freeN(C);
115 }
116
117 /* store */
118
119 bContextStore *CTX_store_add(ListBase *contexts, const char *name, PointerRNA *ptr)
120 {
121         bContextStoreEntry *entry;
122         bContextStore *ctx, *lastctx;
123
124         /* ensure we have a context to put the entry in, if it was already used
125          * we have to copy the context to ensure */
126         ctx = contexts->last;
127
128         if (!ctx || ctx->used) {
129                 if (ctx) {
130                         lastctx = ctx;
131                         ctx = MEM_dupallocN(lastctx);
132                         BLI_duplicatelist(&ctx->entries, &lastctx->entries);
133                 }
134                 else
135                         ctx = MEM_callocN(sizeof(bContextStore), "bContextStore");
136
137                 BLI_addtail(contexts, ctx);
138         }
139
140         entry = MEM_callocN(sizeof(bContextStoreEntry), "bContextStoreEntry");
141         BLI_strncpy(entry->name, name, sizeof(entry->name));
142         entry->ptr = *ptr;
143
144         BLI_addtail(&ctx->entries, entry);
145
146         return ctx;
147 }
148
149 bContextStore *CTX_store_add_all(ListBase *contexts, bContextStore *context)
150 {
151         bContextStoreEntry *entry, *tentry;
152         bContextStore *ctx, *lastctx;
153
154         /* ensure we have a context to put the entries in, if it was already used
155          * we have to copy the context to ensure */
156         ctx = contexts->last;
157
158         if (!ctx || ctx->used) {
159                 if (ctx) {
160                         lastctx = ctx;
161                         ctx = MEM_dupallocN(lastctx);
162                         BLI_duplicatelist(&ctx->entries, &lastctx->entries);
163                 }
164                 else
165                         ctx = MEM_callocN(sizeof(bContextStore), "bContextStore");
166
167                 BLI_addtail(contexts, ctx);
168         }
169
170         for (tentry = context->entries.first; tentry; tentry = tentry->next) {
171                 entry = MEM_dupallocN(tentry);
172                 BLI_addtail(&ctx->entries, entry);
173         }
174
175         return ctx;
176 }
177
178 void CTX_store_set(bContext *C, bContextStore *store)
179 {
180         C->wm.store = store;
181 }
182
183 bContextStore *CTX_store_copy(bContextStore *store)
184 {
185         bContextStore *ctx;
186
187         ctx = MEM_dupallocN(store);
188         BLI_duplicatelist(&ctx->entries, &store->entries);
189
190         return ctx;
191 }
192
193 void CTX_store_free(bContextStore *store)
194 {
195         BLI_freelistN(&store->entries);
196         MEM_freeN(store);
197 }
198
199 void CTX_store_free_list(ListBase *contexts)
200 {
201         bContextStore *ctx;
202
203         while ((ctx = BLI_pophead(contexts))) {
204                 CTX_store_free(ctx);
205         }
206 }
207
208 /* is python initialied? */
209
210 int CTX_py_init_get(bContext *C)
211 {
212         return C->data.py_init;
213 }
214 void CTX_py_init_set(bContext *C, int value)
215 {
216         C->data.py_init = value;
217 }
218
219 void *CTX_py_dict_get(const bContext *C)
220 {
221         return C->data.py_context;
222 }
223 void CTX_py_dict_set(bContext *C, void *value)
224 {
225         C->data.py_context = value;
226 }
227
228 /* data context utility functions */
229
230 struct bContextDataResult {
231         PointerRNA ptr;
232         ListBase list;
233         const char **dir;
234         short type; /* 0: normal, 1: seq */
235 };
236
237 static void *ctx_wm_python_context_get(
238         const bContext *C,
239         const char *member, const StructRNA *member_type,
240         void *fall_through)
241 {
242 #ifdef WITH_PYTHON
243         if (UNLIKELY(C && CTX_py_dict_get(C))) {
244                 bContextDataResult result;
245                 memset(&result, 0, sizeof(bContextDataResult));
246                 BPY_context_member_get((bContext *)C, member, &result);
247
248                 if (result.ptr.data) {
249                         if (RNA_struct_is_a(result.ptr.type, member_type)) {
250                                 return result.ptr.data;
251                         }
252                         else {
253                                 printf("PyContext '%s' is a '%s', expected a '%s'\n",
254                                        member,
255                                        RNA_struct_identifier(result.ptr.type),
256                                        RNA_struct_identifier(member_type));
257                         }
258                 }
259         }
260 #else
261         (void)C, (void)member, (void)member_type;
262 #endif
263
264         /* don't allow UI context access from non-main threads */
265         if (!BLI_thread_is_main())
266                 return NULL;
267
268         return fall_through;
269 }
270
271 static int ctx_data_get(bContext *C, const char *member, bContextDataResult *result)
272 {
273         bScreen *sc;
274         ScrArea *sa;
275         ARegion *ar;
276         int done = 0, recursion = C->data.recursion;
277         int ret = 0;
278
279         memset(result, 0, sizeof(bContextDataResult));
280 #ifdef WITH_PYTHON
281         if (CTX_py_dict_get(C)) {
282                 if (BPY_context_member_get(C, member, result)) {
283                         return 1;
284                 }
285         }
286 #endif
287
288         /* don't allow UI context access from non-main threads */
289         if (!BLI_thread_is_main())
290                 return done;
291
292         /* we check recursion to ensure that we do not get infinite
293          * loops requesting data from ourselves in a context callback */
294
295         /* Ok, this looks evil...
296          * if (ret) done = -(-ret | -done);
297          *
298          * Values in order of importance
299          * (0, -1, 1) - Where 1 is highest priority
300          * */
301         if (done != 1 && recursion < 1 && C->wm.store) {
302                 bContextStoreEntry *entry;
303
304                 C->data.recursion = 1;
305
306                 entry = BLI_rfindstring(&C->wm.store->entries, member, offsetof(bContextStoreEntry, name));
307                 if (entry) {
308                         result->ptr = entry->ptr;
309                         done = 1;
310                 }
311         }
312         if (done != 1 && recursion < 2 && (ar = CTX_wm_region(C))) {
313                 C->data.recursion = 2;
314                 if (ar->type && ar->type->context) {
315                         ret = ar->type->context(C, member, result);
316                         if (ret) done = -(-ret | -done);
317
318                 }
319         }
320         if (done != 1 && recursion < 3 && (sa = CTX_wm_area(C))) {
321                 C->data.recursion = 3;
322                 if (sa->type && sa->type->context) {
323                         ret = sa->type->context(C, member, result);
324                         if (ret) done = -(-ret | -done);
325                 }
326         }
327         if (done != 1 && recursion < 4 && (sc = CTX_wm_screen(C))) {
328                 bContextDataCallback cb = sc->context;
329                 C->data.recursion = 4;
330                 if (cb) {
331                         ret = cb(C, member, result);
332                         if (ret) done = -(-ret | -done);
333                 }
334         }
335
336         C->data.recursion = recursion;
337
338         return done;
339 }
340
341 static void *ctx_data_pointer_get(const bContext *C, const char *member)
342 {
343         bContextDataResult result;
344
345         if (C && ctx_data_get((bContext *)C, member, &result) == 1) {
346                 BLI_assert(result.type == CTX_DATA_TYPE_POINTER);
347                 return result.ptr.data;
348         }
349         else {
350                 return NULL;
351         }
352 }
353
354 static int ctx_data_pointer_verify(const bContext *C, const char *member, void **pointer)
355 {
356         bContextDataResult result;
357
358         /* if context is NULL, pointer must be NULL too and that is a valid return */
359         if (C == NULL) {
360                 *pointer = NULL;
361                 return 1;
362         }
363         else if (ctx_data_get((bContext *)C, member, &result) == 1) {
364                 BLI_assert(result.type == CTX_DATA_TYPE_POINTER);
365                 *pointer = result.ptr.data;
366                 return 1;
367         }
368         else {
369                 *pointer = NULL;
370                 return 0;
371         }
372 }
373
374 static int ctx_data_collection_get(const bContext *C, const char *member, ListBase *list)
375 {
376         bContextDataResult result;
377
378         if (ctx_data_get((bContext *)C, member, &result) == 1) {
379                 BLI_assert(result.type == CTX_DATA_TYPE_COLLECTION);
380                 *list = result.list;
381                 return 1;
382         }
383
384         BLI_listbase_clear(list);
385
386         return 0;
387 }
388
389 PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
390 {
391         bContextDataResult result;
392
393         if (ctx_data_get((bContext *)C, member, &result) == 1) {
394                 BLI_assert(result.type == CTX_DATA_TYPE_POINTER);
395                 return result.ptr;
396         }
397         else {
398                 return PointerRNA_NULL;
399         }
400 }
401
402 PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
403 {
404         PointerRNA ptr = CTX_data_pointer_get(C, member);
405
406         if (ptr.data) {
407                 if (RNA_struct_is_a(ptr.type, type)) {
408                         return ptr;
409                 }
410                 else {
411                         printf("%s: warning, member '%s' is '%s', not '%s'\n",
412                                __func__, member, RNA_struct_identifier(ptr.type), RNA_struct_identifier(type));
413                 }
414         }
415         
416         return PointerRNA_NULL;
417 }
418
419 ListBase CTX_data_collection_get(const bContext *C, const char *member)
420 {
421         bContextDataResult result;
422
423         if (ctx_data_get((bContext *)C, member, &result) == 1) {
424                 BLI_assert(result.type == CTX_DATA_TYPE_COLLECTION);
425                 return result.list;
426         }
427         else {
428                 ListBase list = {NULL, NULL};
429                 return list;
430         }
431 }
432
433 /* 1:found,  -1:found but not set,  0:not found */
434 int CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb, short *r_type)
435 {
436         bContextDataResult result;
437         int ret = ctx_data_get((bContext *)C, member, &result);
438
439         if (ret == 1) {
440                 *r_ptr = result.ptr;
441                 *r_lb = result.list;
442                 *r_type = result.type;
443         }
444         else {
445                 memset(r_ptr, 0, sizeof(*r_ptr));
446                 memset(r_lb, 0, sizeof(*r_lb));
447                 *r_type = 0;
448         }
449
450         return ret;
451 }
452
453 static void data_dir_add(ListBase *lb, const char *member, const bool use_all)
454 {
455         LinkData *link;
456         
457         if ((use_all == false) && strcmp(member, "scene") == 0) /* exception */
458                 return;
459
460         if (BLI_findstring(lb, member, offsetof(LinkData, data)))
461                 return;
462         
463         link = MEM_callocN(sizeof(LinkData), "LinkData");
464         link->data = (void *)member;
465         BLI_addtail(lb, link);
466 }
467
468 /**
469  * \param C Context
470  * \param use_store Use 'C->wm.store'
471  * \param use_rna Use Include the properties from 'RNA_Context'
472  * \param use_all Don't skip values (currently only "scene")
473  */
474 ListBase CTX_data_dir_get_ex(const bContext *C, const bool use_store, const bool use_rna, const bool use_all)
475 {
476         bContextDataResult result;
477         ListBase lb;
478         bScreen *sc;
479         ScrArea *sa;
480         ARegion *ar;
481         int a;
482
483         memset(&lb, 0, sizeof(lb));
484
485         if (use_rna) {
486                 char name[256], *nameptr;
487                 int namelen;
488
489                 PropertyRNA *iterprop;
490                 PointerRNA ctx_ptr;
491                 RNA_pointer_create(NULL, &RNA_Context, (void *)C, &ctx_ptr);
492
493                 iterprop = RNA_struct_iterator_property(ctx_ptr.type);
494
495                 RNA_PROP_BEGIN (&ctx_ptr, itemptr, iterprop)
496                 {
497                         nameptr = RNA_struct_name_get_alloc(&itemptr, name, sizeof(name), &namelen);
498                         data_dir_add(&lb, name, use_all);
499                         if (nameptr) {
500                                 if (name != nameptr) {
501                                         MEM_freeN(nameptr);
502                                 }
503                         }
504                 }
505                 RNA_PROP_END;
506         }
507         if (use_store && C->wm.store) {
508                 bContextStoreEntry *entry;
509
510                 for (entry = C->wm.store->entries.first; entry; entry = entry->next)
511                         data_dir_add(&lb, entry->name, use_all);
512         }
513         if ((ar = CTX_wm_region(C)) && ar->type && ar->type->context) {
514                 memset(&result, 0, sizeof(result));
515                 ar->type->context(C, "", &result);
516
517                 if (result.dir)
518                         for (a = 0; result.dir[a]; a++)
519                                 data_dir_add(&lb, result.dir[a], use_all);
520         }
521         if ((sa = CTX_wm_area(C)) && sa->type && sa->type->context) {
522                 memset(&result, 0, sizeof(result));
523                 sa->type->context(C, "", &result);
524
525                 if (result.dir)
526                         for (a = 0; result.dir[a]; a++)
527                                 data_dir_add(&lb, result.dir[a], use_all);
528         }
529         if ((sc = CTX_wm_screen(C)) && sc->context) {
530                 bContextDataCallback cb = sc->context;
531                 memset(&result, 0, sizeof(result));
532                 cb(C, "", &result);
533
534                 if (result.dir)
535                         for (a = 0; result.dir[a]; a++)
536                                 data_dir_add(&lb, result.dir[a], use_all);
537         }
538
539         return lb;
540 }
541
542 ListBase CTX_data_dir_get(const bContext *C)
543 {
544         return CTX_data_dir_get_ex(C, true, false, false);
545 }
546
547 bool CTX_data_equals(const char *member, const char *str)
548 {
549         return (strcmp(member, str) == 0);
550 }
551
552 bool CTX_data_dir(const char *member)
553 {
554         return member[0] == '\0';
555 }
556
557 void CTX_data_id_pointer_set(bContextDataResult *result, ID *id)
558 {
559         RNA_id_pointer_create(id, &result->ptr);
560 }
561
562 void CTX_data_pointer_set(bContextDataResult *result, ID *id, StructRNA *type, void *data)
563 {
564         RNA_pointer_create(id, type, data, &result->ptr);
565 }
566
567 void CTX_data_id_list_add(bContextDataResult *result, ID *id)
568 {
569         CollectionPointerLink *link;
570
571         link = MEM_callocN(sizeof(CollectionPointerLink), "CTX_data_id_list_add");
572         RNA_id_pointer_create(id, &link->ptr);
573
574         BLI_addtail(&result->list, link);
575 }
576
577 void CTX_data_list_add(bContextDataResult *result, ID *id, StructRNA *type, void *data)
578 {
579         CollectionPointerLink *link;
580
581         link = MEM_callocN(sizeof(CollectionPointerLink), "CTX_data_list_add");
582         RNA_pointer_create(id, type, data, &link->ptr);
583
584         BLI_addtail(&result->list, link);
585 }
586
587 int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBase *))
588 {
589         ListBase list;
590
591         if (func(C, &list)) {
592                 int tot = BLI_countlist(&list);
593                 BLI_freelistN(&list);
594                 return tot;
595         }
596         else
597                 return 0;
598 }
599
600 void CTX_data_dir_set(bContextDataResult *result, const char **dir)
601 {
602         result->dir = dir;
603 }
604
605 void CTX_data_type_set(bContextDataResult *result, short type)
606 {
607         result->type = type;
608 }
609
610 short CTX_data_type_get(bContextDataResult *result)
611 {
612         return result->type;
613 }
614
615
616
617 /* window manager context */
618
619 wmWindowManager *CTX_wm_manager(const bContext *C)
620 {
621         return C->wm.manager;
622 }
623
624 wmWindow *CTX_wm_window(const bContext *C)
625 {
626         return ctx_wm_python_context_get(C, "window", &RNA_Window, C->wm.window);
627 }
628
629 bScreen *CTX_wm_screen(const bContext *C)
630 {
631         return ctx_wm_python_context_get(C, "screen", &RNA_Screen, C->wm.screen);
632 }
633
634 ScrArea *CTX_wm_area(const bContext *C)
635 {
636         return ctx_wm_python_context_get(C, "area", &RNA_Area, C->wm.area);
637 }
638
639 SpaceLink *CTX_wm_space_data(const bContext *C)
640 {
641         ScrArea *sa = CTX_wm_area(C);
642         return (sa) ? sa->spacedata.first : NULL;
643 }
644
645 ARegion *CTX_wm_region(const bContext *C)
646 {
647         return ctx_wm_python_context_get(C, "region", &RNA_Region, C->wm.region);
648 }
649
650 void *CTX_wm_region_data(const bContext *C)
651 {
652         ARegion *ar = CTX_wm_region(C);
653         return (ar) ? ar->regiondata : NULL;
654 }
655
656 struct ARegion *CTX_wm_menu(const bContext *C)
657 {
658         return C->wm.menu;
659 }
660
661 struct ReportList *CTX_wm_reports(const bContext *C)
662 {
663         if (C->wm.manager)
664                 return &(C->wm.manager->reports);
665
666         return NULL;
667 }
668
669 View3D *CTX_wm_view3d(const bContext *C)
670 {
671         ScrArea *sa = CTX_wm_area(C);
672         if (sa && sa->spacetype == SPACE_VIEW3D)
673                 return sa->spacedata.first;
674         return NULL;
675 }
676
677 RegionView3D *CTX_wm_region_view3d(const bContext *C)
678 {
679         ScrArea *sa = CTX_wm_area(C);
680         ARegion *ar = CTX_wm_region(C);
681
682         if (sa && sa->spacetype == SPACE_VIEW3D)
683                 if (ar)
684                         return ar->regiondata;
685         return NULL;
686 }
687
688 struct SpaceText *CTX_wm_space_text(const bContext *C)
689 {
690         ScrArea *sa = CTX_wm_area(C);
691         if (sa && sa->spacetype == SPACE_TEXT)
692                 return sa->spacedata.first;
693         return NULL;
694 }
695
696 struct SpaceConsole *CTX_wm_space_console(const bContext *C)
697 {
698         ScrArea *sa = CTX_wm_area(C);
699         if (sa && sa->spacetype == SPACE_CONSOLE)
700                 return sa->spacedata.first;
701         return NULL;
702 }
703
704 struct SpaceImage *CTX_wm_space_image(const bContext *C)
705 {
706         ScrArea *sa = CTX_wm_area(C);
707         if (sa && sa->spacetype == SPACE_IMAGE)
708                 return sa->spacedata.first;
709         return NULL;
710 }
711
712 struct SpaceButs *CTX_wm_space_buts(const bContext *C)
713 {
714         ScrArea *sa = CTX_wm_area(C);
715         if (sa && sa->spacetype == SPACE_BUTS)
716                 return sa->spacedata.first;
717         return NULL;
718 }
719
720 struct SpaceFile *CTX_wm_space_file(const bContext *C)
721 {
722         ScrArea *sa = CTX_wm_area(C);
723         if (sa && sa->spacetype == SPACE_FILE)
724                 return sa->spacedata.first;
725         return NULL;
726 }
727
728 struct SpaceSeq *CTX_wm_space_seq(const bContext *C)
729 {
730         ScrArea *sa = CTX_wm_area(C);
731         if (sa && sa->spacetype == SPACE_SEQ)
732                 return sa->spacedata.first;
733         return NULL;
734 }
735
736 struct SpaceOops *CTX_wm_space_outliner(const bContext *C)
737 {
738         ScrArea *sa = CTX_wm_area(C);
739         if (sa && sa->spacetype == SPACE_OUTLINER)
740                 return sa->spacedata.first;
741         return NULL;
742 }
743
744 struct SpaceNla *CTX_wm_space_nla(const bContext *C)
745 {
746         ScrArea *sa = CTX_wm_area(C);
747         if (sa && sa->spacetype == SPACE_NLA)
748                 return sa->spacedata.first;
749         return NULL;
750 }
751
752 struct SpaceTime *CTX_wm_space_time(const bContext *C)
753 {
754         ScrArea *sa = CTX_wm_area(C);
755         if (sa && sa->spacetype == SPACE_TIME)
756                 return sa->spacedata.first;
757         return NULL;
758 }
759
760 struct SpaceNode *CTX_wm_space_node(const bContext *C)
761 {
762         ScrArea *sa = CTX_wm_area(C);
763         if (sa && sa->spacetype == SPACE_NODE)
764                 return sa->spacedata.first;
765         return NULL;
766 }
767
768 struct SpaceLogic *CTX_wm_space_logic(const bContext *C)
769 {
770         ScrArea *sa = CTX_wm_area(C);
771         if (sa && sa->spacetype == SPACE_LOGIC)
772                 return sa->spacedata.first;
773         return NULL;
774 }
775
776 struct SpaceIpo *CTX_wm_space_graph(const bContext *C)
777 {
778         ScrArea *sa = CTX_wm_area(C);
779         if (sa && sa->spacetype == SPACE_IPO)
780                 return sa->spacedata.first;
781         return NULL;
782 }
783
784 struct SpaceAction *CTX_wm_space_action(const bContext *C)
785 {
786         ScrArea *sa = CTX_wm_area(C);
787         if (sa && sa->spacetype == SPACE_ACTION)
788                 return sa->spacedata.first;
789         return NULL;
790 }
791
792 struct SpaceInfo *CTX_wm_space_info(const bContext *C)
793 {
794         ScrArea *sa = CTX_wm_area(C);
795         if (sa && sa->spacetype == SPACE_INFO)
796                 return sa->spacedata.first;
797         return NULL;
798 }
799
800 struct SpaceUserPref *CTX_wm_space_userpref(const bContext *C)
801 {
802         ScrArea *sa = CTX_wm_area(C);
803         if (sa && sa->spacetype == SPACE_USERPREF)
804                 return sa->spacedata.first;
805         return NULL;
806 }
807
808 struct SpaceClip *CTX_wm_space_clip(const bContext *C)
809 {
810         ScrArea *sa = CTX_wm_area(C);
811         if (sa && sa->spacetype == SPACE_CLIP)
812                 return sa->spacedata.first;
813         return NULL;
814 }
815
816 void CTX_wm_manager_set(bContext *C, wmWindowManager *wm)
817 {
818         C->wm.manager = wm;
819         C->wm.window = NULL;
820         C->wm.screen = NULL;
821         C->wm.area = NULL;
822         C->wm.region = NULL;
823 }
824
825 void CTX_wm_window_set(bContext *C, wmWindow *win)
826 {
827         C->wm.window = win;
828         C->wm.screen = (win) ? win->screen : NULL;
829         if (C->wm.screen)
830                 C->data.scene = C->wm.screen->scene;
831         C->wm.area = NULL;
832         C->wm.region = NULL;
833 }
834
835 void CTX_wm_screen_set(bContext *C, bScreen *screen)
836 {
837         C->wm.screen = screen;
838         if (C->wm.screen)
839                 C->data.scene = C->wm.screen->scene;
840         C->wm.area = NULL;
841         C->wm.region = NULL;
842 }
843
844 void CTX_wm_area_set(bContext *C, ScrArea *area)
845 {
846         C->wm.area = area;
847         C->wm.region = NULL;
848 }
849
850 void CTX_wm_region_set(bContext *C, ARegion *region)
851 {
852         C->wm.region = region;
853 }
854
855 void CTX_wm_menu_set(bContext *C, ARegion *menu)
856 {
857         C->wm.menu = menu;
858 }
859
860 void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
861 {
862         C->wm.operator_poll_msg = msg;
863 }
864
865 const char *CTX_wm_operator_poll_msg_get(bContext *C)
866 {
867         return IFACE_(C->wm.operator_poll_msg);
868 }
869
870 /* data context */
871
872 Main *CTX_data_main(const bContext *C)
873 {
874         Main *bmain;
875
876         if (ctx_data_pointer_verify(C, "blend_data", (void *)&bmain))
877                 return bmain;
878         else
879                 return C->data.main;
880 }
881
882 void CTX_data_main_set(bContext *C, Main *bmain)
883 {
884         C->data.main = bmain;
885 }
886
887 Scene *CTX_data_scene(const bContext *C)
888 {
889         Scene *scene;
890
891         if (ctx_data_pointer_verify(C, "scene", (void *)&scene))
892                 return scene;
893         else
894                 return C->data.scene;
895 }
896
897 int CTX_data_mode_enum(const bContext *C)
898 {
899         Object *obedit = CTX_data_edit_object(C);
900
901         if (obedit) {
902                 switch (obedit->type) {
903                         case OB_MESH:
904                                 return CTX_MODE_EDIT_MESH;
905                         case OB_CURVE:
906                                 return CTX_MODE_EDIT_CURVE;
907                         case OB_SURF:
908                                 return CTX_MODE_EDIT_SURFACE;
909                         case OB_FONT:
910                                 return CTX_MODE_EDIT_TEXT;
911                         case OB_ARMATURE:
912                                 return CTX_MODE_EDIT_ARMATURE;
913                         case OB_MBALL:
914                                 return CTX_MODE_EDIT_METABALL;
915                         case OB_LATTICE:
916                                 return CTX_MODE_EDIT_LATTICE;
917                 }
918         }
919         else {
920                 Object *ob = CTX_data_active_object(C);
921
922                 if (ob) {
923                         if (ob->mode & OB_MODE_POSE) return CTX_MODE_POSE;
924                         else if (ob->mode & OB_MODE_SCULPT) return CTX_MODE_SCULPT;
925                         else if (ob->mode & OB_MODE_WEIGHT_PAINT) return CTX_MODE_PAINT_WEIGHT;
926                         else if (ob->mode & OB_MODE_VERTEX_PAINT) return CTX_MODE_PAINT_VERTEX;
927                         else if (ob->mode & OB_MODE_TEXTURE_PAINT) return CTX_MODE_PAINT_TEXTURE;
928                         else if (ob->mode & OB_MODE_PARTICLE_EDIT) return CTX_MODE_PARTICLE;
929                 }
930         }
931
932         return CTX_MODE_OBJECT;
933 }
934
935
936 /* would prefer if we can use the enum version below over this one - Campbell */
937 /* must be aligned with above enum  */
938 static const char *data_mode_strings[] = {
939         "mesh_edit",
940         "curve_edit",
941         "surface_edit",
942         "text_edit",
943         "armature_edit",
944         "mball_edit",
945         "lattice_edit",
946         "posemode",
947         "sculpt_mode",
948         "weightpaint",
949         "vertexpaint",
950         "imagepaint",
951         "particlemode",
952         "objectmode",
953         NULL
954 };
955 const char *CTX_data_mode_string(const bContext *C)
956 {
957         return data_mode_strings[CTX_data_mode_enum(C)];
958 }
959
960 void CTX_data_scene_set(bContext *C, Scene *scene)
961 {
962         C->data.scene = scene;
963 }
964
965 ToolSettings *CTX_data_tool_settings(const bContext *C)
966 {
967         Scene *scene = CTX_data_scene(C);
968
969         if (scene)
970                 return scene->toolsettings;
971         else
972                 return NULL;
973 }
974
975 int CTX_data_selected_nodes(const bContext *C, ListBase *list)
976 {
977         return ctx_data_collection_get(C, "selected_nodes", list);
978 }
979
980 int CTX_data_selected_editable_objects(const bContext *C, ListBase *list)
981 {
982         return ctx_data_collection_get(C, "selected_editable_objects", list);
983 }
984
985 int CTX_data_selected_editable_bases(const bContext *C, ListBase *list)
986 {
987         return ctx_data_collection_get(C, "selected_editable_bases", list);
988 }
989
990 int CTX_data_selected_objects(const bContext *C, ListBase *list)
991 {
992         return ctx_data_collection_get(C, "selected_objects", list);
993 }
994
995 int CTX_data_selected_bases(const bContext *C, ListBase *list)
996 {
997         return ctx_data_collection_get(C, "selected_bases", list);
998 }
999
1000 int CTX_data_visible_objects(const bContext *C, ListBase *list)
1001 {
1002         return ctx_data_collection_get(C, "visible_objects", list);
1003 }
1004
1005 int CTX_data_visible_bases(const bContext *C, ListBase *list)
1006 {
1007         return ctx_data_collection_get(C, "visible_bases", list);
1008 }
1009
1010 int CTX_data_selectable_objects(const bContext *C, ListBase *list)
1011 {
1012         return ctx_data_collection_get(C, "selectable_objects", list);
1013 }
1014
1015 int CTX_data_selectable_bases(const bContext *C, ListBase *list)
1016 {
1017         return ctx_data_collection_get(C, "selectable_bases", list);
1018 }
1019
1020 struct Object *CTX_data_active_object(const bContext *C)
1021 {
1022         return ctx_data_pointer_get(C, "active_object");
1023 }
1024
1025 struct Base *CTX_data_active_base(const bContext *C)
1026 {
1027         return ctx_data_pointer_get(C, "active_base");
1028 }
1029
1030 struct Object *CTX_data_edit_object(const bContext *C)
1031 {
1032         return ctx_data_pointer_get(C, "edit_object");
1033 }
1034
1035 struct Image *CTX_data_edit_image(const bContext *C)
1036 {
1037         return ctx_data_pointer_get(C, "edit_image");
1038 }
1039
1040 struct Text *CTX_data_edit_text(const bContext *C)
1041 {
1042         return ctx_data_pointer_get(C, "edit_text");
1043 }
1044
1045 struct MovieClip *CTX_data_edit_movieclip(const bContext *C)
1046 {
1047         return ctx_data_pointer_get(C, "edit_movieclip");
1048 }
1049
1050 struct Mask *CTX_data_edit_mask(const bContext *C)
1051 {
1052         return ctx_data_pointer_get(C, "edit_mask");
1053 }
1054
1055 struct EditBone *CTX_data_active_bone(const bContext *C)
1056 {
1057         return ctx_data_pointer_get(C, "active_bone");
1058 }
1059
1060 int CTX_data_selected_bones(const bContext *C, ListBase *list)
1061 {
1062         return ctx_data_collection_get(C, "selected_bones", list);
1063 }
1064
1065 int CTX_data_selected_editable_bones(const bContext *C, ListBase *list)
1066 {
1067         return ctx_data_collection_get(C, "selected_editable_bones", list);
1068 }
1069
1070 int CTX_data_visible_bones(const bContext *C, ListBase *list)
1071 {
1072         return ctx_data_collection_get(C, "visible_bones", list);
1073 }
1074
1075 int CTX_data_editable_bones(const bContext *C, ListBase *list)
1076 {
1077         return ctx_data_collection_get(C, "editable_bones", list);
1078 }
1079
1080 struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C)
1081 {
1082         return ctx_data_pointer_get(C, "active_pose_bone");
1083 }
1084
1085 int CTX_data_selected_pose_bones(const bContext *C, ListBase *list)
1086 {
1087         return ctx_data_collection_get(C, "selected_pose_bones", list);
1088 }
1089
1090 int CTX_data_visible_pose_bones(const bContext *C, ListBase *list)
1091 {
1092         return ctx_data_collection_get(C, "visible_pose_bones", list);
1093 }
1094
1095 FreestyleLineStyle *CTX_data_linestyle_from_scene(Scene *scene)
1096 {
1097         SceneRenderLayer *actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay);
1098         FreestyleConfig *config = &actsrl->freestyleConfig;
1099         FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
1100
1101         if (lineset) {
1102                 return lineset->linestyle;
1103         }
1104
1105         return NULL;
1106 }