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