First of all thanks Kent Mein for committing the fix to space.c and Peter den Bak...
[blender.git] / source / blender / python / BPY_menus.c
1 /* 
2  *
3  * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. The Blender
9  * Foundation also sells licenses for use in proprietary software under
10  * the Blender License.  See http://www.blender.org/BL/ for information
11  * about this.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21  *
22  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
23  * All rights reserved.
24  *
25  * This is a new part of Blender.
26  *
27  * Contributor(s): Willian P. Germano
28  *
29  * ***** END GPL/BL DUAL LICENSE BLOCK *****
30 */
31
32 /* This is the main file responsible for having bpython scripts accessible
33  * from Blender menus.  To know more, please start with its header file.
34 */
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <Python.h>
46
47 #ifndef WIN32
48 #include <dirent.h>
49 #else
50 #include "BLI_winstuff.h"
51 #include <io.h>
52 #include <direct.h>
53 #endif 
54
55 #include "BKE_global.h"
56 #include "BKE_utildefines.h"
57 #include "BLI_blenlib.h"
58 #include "MEM_guardedalloc.h"
59
60 #include <DNA_userdef_types.h> /* for U.pythondir */
61
62 #include "BPY_extern.h"
63 #include "BPY_menus.h"
64
65 #include <errno.h>
66
67 #define BPYMENU_DATAFILE "Bpymenus"
68
69 static int DEBUG;
70
71 /* BPyMenuTable holds all registered pymenus, as linked lists for each menu
72  * where they can appear (see PYMENUHOOKS enum in BPY_menus.h).
73 */
74 BPyMenu *BPyMenuTable[PYMENU_TOTAL];
75
76 static int bpymenu_group_atoi (char *str)
77 {
78         if (!strcmp(str, "Import")) return PYMENU_IMPORT;
79         else if (!strcmp(str, "Export")) return PYMENU_EXPORT;
80         else if (!strcmp(str, "Help")) return PYMENU_HELP;
81         else if (!strcmp(str, "Websites") || !strcmp(str, "HelpWebsites"))
82                 return PYMENU_HELPWEBSITES;
83         else if (!strcmp(str, "System") || !strcmp(str, "HelpSystem"))
84                 return PYMENU_HELPSYSTEM;
85         else if (!strcmp(str, "Add")) return PYMENU_ADD;
86         else if (!strcmp(str, "Mesh")) return PYMENU_MESH;
87         else if (!strcmp(str, "Wizards")) return PYMENU_WIZARDS;
88         else if (!strcmp(str, "Animation")) return PYMENU_ANIMATION;
89         else if (!strcmp(str, "Materials")) return PYMENU_MATERIALS;
90         else if (!strcmp(str, "UV")) return PYMENU_UV;
91         else if (!strcmp(str, "Object")) return PYMENU_OBJECT;
92         /* "Misc" or an inexistent group name: use misc */
93         else return PYMENU_MISC;
94 }
95
96 char *BPyMenu_group_itoa (short menugroup)
97 {
98         switch (menugroup) {
99                 case PYMENU_IMPORT:
100                         return "Import";
101                         break;
102                 case PYMENU_EXPORT:
103                         return "Export";
104                         break;
105                 case PYMENU_ADD:
106                         return "Add";
107                         break;
108                 case PYMENU_HELP:
109                         return "Help";
110                         break;
111                 case PYMENU_HELPWEBSITES:
112                         return "Websites";
113                         break;
114                 case PYMENU_HELPSYSTEM:
115                         return "System";
116                         break;
117                 case PYMENU_MESH:
118                         return "Mesh";
119                         break;
120                 case PYMENU_WIZARDS:
121                         return "Wizards";
122                         break;
123                 case PYMENU_ANIMATION:
124                         return "Animation";
125                         break;
126                 case PYMENU_MATERIALS:
127                         return "Materials";
128                         break;
129                 case PYMENU_UV:
130                         return "UV";
131                         break;
132                 case PYMENU_OBJECT:
133                         return "Object";
134                         break;
135                 case PYMENU_MISC:
136                         return "Misc";
137                         break;
138         }
139         return NULL;
140 }
141
142 /* BPyMenu_CreatePupmenuStr:
143  * build and return a meaninful string to be used by pupmenu().  The
144  * string is made of a bpymenu name as title and its submenus as possible
145  * choices for the user.
146 */
147 char *BPyMenu_CreatePupmenuStr(BPyMenu *pym, short menugroup)
148 {
149         BPySubMenu *pysm = pym->submenus;
150         char str[1024], str2[100];
151         int i = 0, rlen;
152
153         if (!pym || !pysm) return NULL;
154
155         str[0] = '\0';
156
157         PyOS_snprintf(str2, sizeof(str2), "%s: %s%%t",
158                 BPyMenu_group_itoa(menugroup), pym->name);
159         strcat(str, str2);
160
161         while (pysm) {
162                 PyOS_snprintf(str2, sizeof(str2), "|%s%%x%d", pysm->name, i);
163                 rlen = sizeof(str) - strlen(str);
164                 strncat(str, str2, rlen);
165                 i++;
166                 pysm = pysm->next;
167         }
168
169         return BLI_strdup(str);
170 }
171
172 static void bpymenu_RemoveAllSubEntries (BPySubMenu *smenu)
173 {
174         BPySubMenu *tmp;
175
176         while (smenu) {
177                 tmp = smenu->next;
178                 if (smenu->name) MEM_freeN(smenu->name);
179                 if (smenu->arg)  MEM_freeN(smenu->arg);
180                 MEM_freeN(smenu);
181                 smenu = tmp;
182         }
183         return;
184 }
185
186 void BPyMenu_RemoveAllEntries (void)
187 {
188         BPyMenu *tmp, *pymenu;
189         int i;
190
191         for (i = 0; i < PYMENU_TOTAL; i++) {
192                 pymenu = BPyMenuTable[i];
193                 while (pymenu) {
194                         tmp = pymenu->next;
195                         if (pymenu->name) MEM_freeN(pymenu->name);
196                         if (pymenu->filename) MEM_freeN(pymenu->filename);
197                         if (pymenu->tooltip) MEM_freeN(pymenu->tooltip);
198                         if (pymenu->submenus) bpymenu_RemoveAllSubEntries(pymenu->submenus);
199                         MEM_freeN(pymenu);
200                         pymenu = tmp;
201                 }
202                 BPyMenuTable[i] = NULL;
203         }
204         return;
205 }
206
207 static BPyMenu *bpymenu_FindEntry (short group, char *name)
208 {
209         BPyMenu *pymenu;
210
211         if ((group <0) || (group >= PYMENU_TOTAL)) return NULL;
212
213         pymenu = BPyMenuTable[group];
214
215         while (pymenu) {
216                 if (!strcmp(pymenu->name, name)) return pymenu;
217                 pymenu = pymenu->next;
218         }
219
220         return NULL;
221 }
222
223 /* BPyMenu_GetEntry:
224  * given a group and a position, return the entry in that position from
225  * that group.
226 */ 
227 BPyMenu *BPyMenu_GetEntry (short group, short pos)
228 {
229         BPyMenu *pym = NULL;
230
231         if ((group < 0) || (group >= PYMENU_TOTAL)) return NULL;
232
233         pym = BPyMenuTable[group];
234
235         while (pos--) {
236                 if (pym) pym = pym->next;
237                 else break;
238         }
239
240         return pym; /* found entry or NULL */
241 }
242         
243 static void bpymenu_set_tooltip (BPyMenu *pymenu, char *tip)
244 {
245         if (!pymenu) return;
246
247         if (pymenu->tooltip) MEM_freeN(pymenu->tooltip);
248         pymenu->tooltip = BLI_strdup(tip);
249
250         return;
251 }
252
253 /* bpymenu_AddEntry:
254  * try to find an existing pymenu entry with the given type and name;
255  * if found, update it with new info, otherwise create a new one and fill it.
256  */
257 static BPyMenu *bpymenu_AddEntry (short group, short version, char *name,
258         char *fname, int whichdir, char *tooltip)
259 {
260         BPyMenu *menu, *next = NULL, **iter;
261         int nameclash = 0;
262
263         if ((group < 0) || (group >= PYMENU_TOTAL)) return NULL;
264         if (!name || !fname) return NULL;
265
266         menu = bpymenu_FindEntry (group, name); /* already exists? */
267
268         /* if a menu with this name already exists in the same group:
269          * - if one script is in the default dir and the other in U.pythondir,
270          *   accept and let the new one override the other.
271          * - otherwise, report the error and return NULL. */
272         if (menu) {
273                 if (menu->dir < whichdir) { /* new one is in U.pythondir */
274                         nameclash = 1;
275                         if (menu->name) MEM_freeN(menu->name);
276                         if (menu->filename) MEM_freeN(menu->filename);
277                         if (menu->tooltip) MEM_freeN(menu->tooltip);
278                         if (menu->submenus) bpymenu_RemoveAllSubEntries(menu->submenus);
279                         next = menu->next;
280                 }
281                 else { /* they are in the same dir */
282                         if (DEBUG) {
283                                 printf("\nWarning: script %s's menu name is already in use.\n", fname);
284                                 printf ("Edit the script and change its Name: '%s' field, please.\n"
285                                                         "Note: if you really want two scripts in the same menu with\n"
286                                                         "the same name, keep one in the default dir and the other in\n"
287                                                         "the user defined dir, where it will take precedence.\n", name);
288                         }
289                         return NULL;
290                 }
291         }
292         else menu = MEM_mallocN(sizeof(BPyMenu), "pymenu");
293
294         if (!menu) return NULL;
295
296         menu->name = BLI_strdup(name);
297         menu->version = version;
298         menu->filename = BLI_strdup(fname);
299         menu->tooltip = NULL;
300         if (tooltip) menu->tooltip = BLI_strdup(tooltip);
301         menu->dir = whichdir;
302         menu->submenus = NULL;
303         menu->next = next; /* non-NULL if menu already existed */
304
305         if (nameclash) return menu; /* no need to place it, it's already at the list*/
306         else { /* insert the new entry in its correct position at the table */
307                 BPyMenu *prev = NULL;
308                 char *s = NULL;
309
310                 iter = &BPyMenuTable[group];
311                 while (*iter) {
312                         s = (*iter)->name;
313                         if (s) if (strcmp(menu->name, s) < 0) break; /* sort by names */
314                         prev = *iter;
315                         iter = &((*iter)->next);
316                 }
317
318                 if (*iter) { /* prepend */
319                         menu->next = *iter;
320                         if (prev) prev->next = menu;
321                         else BPyMenuTable[group] = menu; /* is first entry */
322                 }
323                 else *iter = menu; /* append */
324         }
325
326         return menu;
327 }
328
329 /* bpymenu_AddSubEntry:
330  * add a submenu to an existing python menu.
331  */
332 static int bpymenu_AddSubEntry (BPyMenu *mentry, char *name, char *arg)
333 {
334         BPySubMenu *smenu, **iter;
335
336         smenu = MEM_mallocN(sizeof(BPySubMenu), "pysubmenu");
337         if (!smenu) return -1;
338
339         smenu->name = BLI_strdup(name);
340         smenu->arg = BLI_strdup(arg);
341         smenu->next = NULL;
342
343         if (!smenu->name || !smenu->arg) return -1;
344
345         iter = &(mentry->submenus);
346         while (*iter) iter = &((*iter)->next);
347
348         *iter = smenu;
349
350         return 0;
351 }
352
353 /* bpymenu_CreateFromFile:
354  * parse the bpymenus data file where Python menu data is stored;
355  * based on this data, create and fill the pymenu structs.
356  */
357 static int bpymenu_CreateFromFile (void)
358 {
359         FILE *fp;
360         char line[255], w1[255], w2[255], tooltip[255], *tip;
361         int parsing, version, whichdir;
362         short group;
363         BPyMenu *pymenu = NULL;
364
365         /* init global bpymenu table (it is a list of pointers to struct BPyMenus
366          * for each available cathegory: import, export, etc.) */
367         for (group = 0; group < PYMENU_TOTAL; group++)
368                 BPyMenuTable[group] = NULL;
369
370         /* let's try to open the file with bpymenu data */
371         BLI_make_file_string ("/", line, bpy_gethome(), BPYMENU_DATAFILE);
372
373         fp = fopen(line, "rb");
374
375         if (!fp) {
376                 if (DEBUG) printf("BPyMenus error: couldn't open config file %s.\n", line);
377                 return -1;
378         }
379
380         fgets(line, 255, fp); /* header */
381
382         /* check if the U.pythondir we saved at the file is different from the
383          * current one.  If so, return to force updating from dirs */
384         w1[0] = '\0';
385         fscanf(fp, "# User defined scripts dir: %[^\n]\n", w1);
386         if (w1) {
387                 if (strcmp(w1, U.pythondir) != 0) return -1;
388                 w1[0] = '\0';
389         }
390
391         while (fgets(line, 255, fp)) { /* parsing file lines */
392
393                 switch (line[0]) { /* check first char */
394                         case '#': /* comment */
395                                 continue;
396                                 break;
397                         case '\n':
398                                 continue;
399                                 break;
400                         default:
401                                 parsing = sscanf(line, "%s {\n", w1); /* menu group */
402                                 break;
403                 }
404
405                 if (parsing == 1) { /* got menu group string */
406                         group = bpymenu_group_atoi(w1);
407                         if (group < 0 && DEBUG) { /* invalid type */
408                                 printf("BPyMenus error parsing config file: wrong group: %s, "
409                                         "will use 'Misc'.\n", w1);
410                         }
411                 }
412                 else continue;
413
414                 while (1) {
415                         tip = NULL; /* optional tooltip */
416                         fgets(line, 255, fp);
417                         if (line[0] == '}') break;
418                         else if (line[0] == '\n') continue;
419                         else if (line[0] == '\'') { /* menu entry */
420                                 parsing = sscanf(line, "'%[^']' %d %s %d '%[^']'\n", w1, &version, w2, &whichdir, tooltip);
421
422                                 if (parsing <= 0) { /* invalid line, get rid of it */
423                                         fgets(line, 255, fp);
424                                 }
425                                 else if (parsing == 5) tip = tooltip; /* has tooltip */
426
427                                 pymenu = bpymenu_AddEntry(group, (short)version, w1, w2, whichdir, tip);
428                                 if (!pymenu) {
429                                         puts("BPyMenus error: couldn't create bpymenu entry.\n");
430                                         fclose(fp);
431                                         return -1;
432                                 }
433                         }
434                         else if (line[0] == '|' && line[1] == '_') { /* menu sub-entry */
435                                 if (!pymenu) continue; /* no menu yet, skip this line */
436                                 sscanf(line, "|_%[^:]: %s\n", w1, w2);
437                                 bpymenu_AddSubEntry(pymenu, w1, w2);
438                         }
439                 }
440         }
441
442         fclose(fp);
443         return 0;
444 }
445
446 /* bpymenu_WriteDataFile:
447  * writes the registered scripts info to the user's home dir, for faster
448  * access when the scripts dir hasn't changed.
449 */
450 static void bpymenu_WriteDataFile(void)
451 {
452         BPyMenu *pymenu;
453         BPySubMenu *smenu;
454         FILE *fp;
455         char fname[FILE_MAXDIR+FILE_MAXFILE];
456         int i;
457
458         BLI_make_file_string("/", fname, bpy_gethome(), BPYMENU_DATAFILE);
459
460         fp = fopen(fname, "w");
461         if (!fp) {
462                 if (DEBUG) printf("BPyMenus error: couldn't write %s file.", fname);
463                 return;
464         }
465
466         fprintf(fp, "# Blender: registered menu entries for bpython scripts\n");
467
468         if (U.pythondir[0] != '\0')
469                 fprintf(fp, "# User defined scripts dir: %s\n", U.pythondir);
470
471         for (i = 0; i < PYMENU_TOTAL; i++) {
472                 pymenu = BPyMenuTable[i];
473                 if (!pymenu) continue;
474                 fprintf(fp, "\n%s {\n", BPyMenu_group_itoa(i));
475                 while (pymenu) {
476                         fprintf(fp,"'%s' %d %s %d", pymenu->name, pymenu->version, pymenu->filename, pymenu->dir);
477                         if (pymenu->tooltip) fprintf(fp, " '%s'\n", pymenu->tooltip);
478                         else fprintf(fp, "\n");
479                         smenu = pymenu->submenus;
480                         while (smenu) {
481                                 fprintf(fp, "|_%s: %s\n", smenu->name, smenu->arg);
482                                 smenu = smenu->next;
483                         }
484                         pymenu = pymenu->next;
485                 }
486                 fprintf(fp, "}\n");
487         }
488
489         fclose(fp);
490         return;
491 }
492
493 /* BPyMenu_PrintAllEntries:
494  * useful for debugging.
495 */
496 void BPyMenu_PrintAllEntries(void)
497 {
498         BPyMenu *pymenu;
499         BPySubMenu *smenu;
500         int i;
501
502         printf("# Blender: registered menu entries for bpython scripts\n");
503
504         for (i = 0; i < PYMENU_TOTAL; i++) {
505                 pymenu = BPyMenuTable[i];
506                 printf("\n%s {\n", BPyMenu_group_itoa(i));
507                 while (pymenu) {
508                         printf("'%s' %d %s %d", pymenu->name, pymenu->version, pymenu->filename, pymenu->dir);
509                         if (pymenu->tooltip) printf(" '%s'\n", pymenu->tooltip);
510                         else printf("\n");
511                         smenu = pymenu->submenus;
512                         while (smenu) {
513                                 printf("|_%s: %s\n", smenu->name, smenu->arg);
514                                 smenu = smenu->next;
515                         }
516                         pymenu = pymenu->next;
517                 }
518                 printf("}\n");
519         }
520 }
521
522 /* bpymenu_GetDataFromDir:
523  * this function scans the scripts dir looking for .py files with the
524  * right header and menu info, using that to fill the bpymenu structs.
525  * whichdir defines if the script is in the default scripts dir or the
526  * user defined one (U.pythondir: whichdir == 1).
527  * Speed is important.
528 */
529 static int bpymenu_CreateFromDir (char *dirname, int whichdir)
530 {
531         DIR *dir;
532         FILE *fp;
533         struct stat st;
534         struct dirent *dir_entry;
535         BPyMenu *pymenu;
536         char *s, *fname, str[FILE_MAXFILE+FILE_MAXDIR];
537         char line[100], w[100];
538         char name[100], submenu[100], subarg[100], tooltip[100];
539         int res = 0, version = 0;
540
541         dir = opendir(dirname);
542
543         if (!dir) return -1;
544
545 /* we scan the dir for filenames ending with .py and starting with the
546  * right 'magic number': '#!BPY'.  All others are ignored. */
547
548         while ((dir_entry = readdir(dir)) != NULL) {
549                 fname = dir_entry->d_name;
550                 /* ignore anything starting with a dot */
551                 if (fname[0] == '.') continue; /* like . and .. */
552
553                 /* also skip filenames whose extension isn't '.py' */
554                 s = strstr(fname, ".py");
555                 if (!s || *(s+3) != '\0') continue;
556
557                 BLI_make_file_string("/", str, dirname, fname);
558
559                 /* paranoia: check if this is really a file and not a disguised dir */
560                 if ((stat(str, &st) == -1) || !S_ISREG(st.st_mode)) continue;
561
562                 fp = fopen(str, "rb");
563
564                 if (!fp) {
565                         if (DEBUG) printf("BPyMenus error: couldn't open %s.\n", str);
566                         continue;
567                 }
568
569                 /* finally, look for the start string '#!BPY', with
570                  * or w/o white space(s) between #! and BPY */
571                 fgets(line, 100, fp);
572                 if (line[0] != '#' || line[1] != '!') goto discard;
573
574                 if (!strstr (line, "BPY")) goto discard;
575
576                 /* file passed the tests, look for the three double-quotes */
577                 while (fgets(line, 100, fp)) {
578                         if (line[0] == '"' && line[1] == '"' && line[2] == '"') {
579                                 res = 1; /* found */
580                                 break;
581                         }
582                 }
583
584                 if (!res) goto discard;
585
586                 /* Now we're ready to get the registration info.  A little more structure
587                  * was imposed to their format, for speed. The registration
588                  * lines must appear between the first pair of triple double-quotes and
589                  * follow this order (the single-quotes are part of the format):
590                  * 
591                  * Name: 'script name for the menu'
592                  * Group: 'group name' (defines menu)
593                  * Blender: <short int> (minimal Blender version)
594                  * Submenu: 'submenu name' related_1word_arg
595                  * Tooltip: 'tooltip for the menu'
596                  *
597                  * notes:
598                  * - there may be more than one submenu line, or none:
599                  * submenus and the tooltip are optional;
600                  * - the Blender version is the same number reported by
601                  * Blender.Get('version') in BPython or G.version in C;
602                  * - only the first letter of each token is checked, both lower
603                  * and upper cases, so that's all that matters for recognition:
604                  * n 'script name' is enough for the name line, for example. */ 
605
606                 /* first the name: */
607                 res = fscanf(fp, "%[^']'%[^'\r\n]'\n", w, name);
608                 if ((res != 2) || (w[0] != 'n' && w[0] != 'N')) {
609                         if (DEBUG) printf("BPyMenus error: wrong 'name' line in %s.\n", str);
610                         goto discard;
611                 }
612
613                 line[0] = '\0'; /* used as group for this part */
614
615                 /* minimal Blender version: */
616                 res = fscanf(fp, "%s %d\n", w, &version);
617                 if ((res != 2) || (w[0] != 'b' && w[0] != 'B')) {
618                         if (DEBUG) printf("BPyMenus error: wrong 'blender' line in %s.\n", str);
619                         goto discard;
620                 }
621
622                 /* the group: */
623                 res = fscanf(fp, "%[^']'%[^'\r\n]'\n", w, line);
624                 if ((res != 2) || (w[0] != 'g' && w[0] != 'G')) {
625                         if (DEBUG) printf("BPyMenus error: wrong 'group' line in %s.\n", str);
626                         goto discard;
627                 }
628
629                 res = bpymenu_group_atoi(line);
630                 if (res < 0) {
631                         if (DEBUG) printf("BPyMenus error: unknown 'group' %s in %s.\n", line, str);
632                         goto discard;
633                 }
634
635                 pymenu = bpymenu_AddEntry(res, (short)version, name, fname, whichdir, NULL);
636                 if (!pymenu) {
637                         if (DEBUG) printf("BPyMenus error: couldn't create entry for %s.\n", str);
638                         fclose(fp);
639                         closedir(dir);
640                         return -2;
641                 }
642
643                 /* the (optional) submenu(s): */
644                 while (fgets (line, 100, fp)) {
645                         res = sscanf(line, "%[^']'%[^'\r\n]'%s\n", w, submenu, subarg);
646                         if ((res != 3) || (w[0] != 's' && w[0] != 'S')) break;
647                         bpymenu_AddSubEntry(pymenu, submenu, subarg); 
648                 }       
649
650                 /* the (optional) tooltip: */
651                 res = sscanf(line, "%[^']'%[^'\r\n]'\n", w, tooltip);
652                 if ((res == 2) && (w[0] == 't' || w[0] == 'T')) {
653                         bpymenu_set_tooltip (pymenu, tooltip);
654                 }
655
656 discard:
657                 fclose (fp);
658                 continue;
659         }
660
661         closedir(dir);
662         return 0;
663 }
664
665 static int bpymenu_GetStatMTime(char *name, int is_file, time_t* mtime)
666 {
667         struct stat st;
668         int result;
669
670         result = stat(name, &st);
671
672         if (result == -1) return -1;
673
674         if (is_file) { if (!S_ISREG(st.st_mode)) return -2;     }
675         else if (!S_ISDIR(st.st_mode)) return -2;
676
677         *mtime = st.st_mtime;
678
679         return 0;
680 }
681
682 /* BPyMenu_Init:
683  * import the bpython menus data to Blender, either from:
684  * - the BPYMENU_DATAFILE file (?/.blender/Bpymenus) or
685  * - the scripts dir(s), case newer than the datafile (then update the file).
686  * then fill the bpymenu table with this data.
687  * if param usedir != 0, then the data is recreated from the dir(s) anyway.
688 */
689 int BPyMenu_Init(int usedir)
690 {
691         char fname[FILE_MAXDIR+FILE_MAXFILE];
692         char dirname[FILE_MAXDIR];
693         char *upydir = U.pythondir;
694         time_t tdir1 = 0, tdir2 = 0, tfile = 0;
695         int res1 = 0, res2 = 0, resf = 0;
696
697         DEBUG = G.f & G_DEBUG; /* is Blender in debug mode (started with -d) ? */
698
699         /* init global bpymenu table (it is a list of pointers to struct BPyMenus
700          * for each available group: import, export, etc.) */
701         for (res1 = 0; res1 < PYMENU_TOTAL; res1++)
702                 BPyMenuTable[res1] = NULL;
703
704         if (U.pythondir[0] == '\0') upydir = NULL;
705
706         BLI_make_file_string ("/", dirname, bpy_gethome(), "scripts");
707
708         res1 = bpymenu_GetStatMTime(dirname, 0, &tdir1);
709
710         if (res1 < 0) {
711                 tdir1 = 0;
712                 if (DEBUG) {
713                         printf ("\nDefault scripts dir: %s:\n%s\n", dirname, strerror(errno));
714                         if (upydir)
715                                 printf("Getting scripts menu data from user defined dir: %s.\n",upydir);
716                 }
717         }
718         else { syspath_append(dirname); }
719
720         if (upydir) {
721                 res2 = bpymenu_GetStatMTime(U.pythondir, 0, &tdir2);
722
723                 if (res2 < 0) {
724                         tdir2 = 0;
725                         if (DEBUG) printf("\nUser defined scripts dir: %s:\n%s.\n", upydir, strerror(errno));
726                         if (res1 < 0) {
727                         if (DEBUG) printf ("To have scripts in menus, please add them to the"
728                                                         "default scripts dir: %s\n"
729                                                         "and/or go to 'Info window -> File Paths tab' and set a valid\n"
730                                                         "path for the user defined scripts dir.\n", dirname);
731                         return -1;
732                         }
733                 }
734         }
735         else res2 = -1;
736
737         if ((res1 < 0) && (res2 < 0)) {
738                 if (DEBUG) {
739                         printf ("\nCannot register scripts in menus, no scripts dir"
740                                                         " available.\nExpected default dir in %s .\n", dirname);
741                 }
742                 return -1;
743         }
744
745         if (DEBUG) printf("\nRegistering scripts in Blender menus ...\n\n");
746
747         if (!usedir) { /* if we're not forced to use the dir */
748                 BLI_make_file_string("/", fname, bpy_gethome(), BPYMENU_DATAFILE);
749                 resf = bpymenu_GetStatMTime(fname, 1, &tfile);
750                 if (resf < 0) tfile = 0;
751         }
752
753         /* comparing dates */
754
755         if ((tfile > tdir1) && (tfile > tdir2) && !resf) { /* file is newer */
756                 resf = bpymenu_CreateFromFile(); /* -1 if an error occurred */
757                 if (!resf && DEBUG)
758                         printf("Getting menu data for scripts from file: %s\n\n", fname);
759         }
760         else resf = -1; /* -1 to use dirs: didn't use file or it was corrupted */
761
762         if (resf == -1) { /* use dirs */
763                 if (DEBUG) {
764                         printf("Getting menu data for scripts from dir(s):\n%s\n", dirname);
765                         if (upydir) printf("%s\n", upydir);
766                 }
767                 if (res1 == 0) bpymenu_CreateFromDir(dirname, 0);
768                 if (res2 == 0) bpymenu_CreateFromDir(U.pythondir, 1);
769
770                 /* check if we got any data */
771                 for (res1 = 0; res1 < PYMENU_TOTAL; res1++)
772                         if (BPyMenuTable[res1]) break;
773
774                 /* if we got, recreate the file */
775                 if (res1 < PYMENU_TOTAL) bpymenu_WriteDataFile();
776                 else if (DEBUG) {
777                         printf ("\nWarning: Registering scripts in menus -- no info found.\n"
778                                                         "Either your scripts dirs have no .py scripts or the scripts\n"
779                                                         "don't have a header with registration data.\n"
780                                                         "Default scripts dir is: %s\n", dirname);
781                         if (upydir)
782                                 printf("User defined scripts dir is: %s\n", upydir);
783                 }
784
785                 return 0;
786         }
787
788         return 0;
789 }