2.5
[blender.git] / source / blender / windowmanager / intern / wm_report.c
1
2 #include "MEM_guardedalloc.h"
3
4 #include "DNA_windowmanager_types.h"
5
6 #include "BLI_blenlib.h"
7
8 #include "BKE_global.h"
9
10 #include "WM_api.h"
11 #include "WM_types.h"
12
13 #include <stdarg.h>
14 #include <stdio.h>
15 #include <string.h>
16
17 #ifdef _WIN32
18 #ifndef vsnprintf
19 #define vsnprintf _vsnprintf
20 #endif
21 #endif
22
23 static int wmReportLevel= WM_LOG_INFO;
24 static int wmReportPrint= 0;
25
26 static const char *wm_report_type_str(int type)
27 {
28         switch(type) {
29                 case WM_LOG_DEBUG: return "Debug";
30                 case WM_LOG_INFO: return "Info";
31                 case WM_LOG_WARNING: return "Warning";
32                 case WM_ERROR_UNDEFINED: return "Error";
33                 case WM_ERROR_INVALID_INPUT: return "Invalid Input Error";
34                 case WM_ERROR_INVALID_CONTEXT: return "Invalid Context Error";
35                 case WM_ERROR_OUT_OF_MEMORY: return "Out Of Memory Error";
36                 default: return "Undefined Type";
37         }
38 }
39
40 static void wm_print_report(wmReport *report)
41 {
42         printf("%s: %s\n", report->typestr, report->message);
43         fflush(stdout); /* this ensures the message is printed before a crash */
44 }
45
46 void WM_report(bContext *C, int type, const char *message)
47 {
48         wmReport *report;
49         int len;
50
51         if(!C->wm) {
52                 fprintf(stderr, "WM_report: can't report without windowmanager.\n");
53                 return;
54         }
55         if(type < wmReportLevel)
56                 return;
57
58         report= MEM_callocN(sizeof(wmReport), "wmReport");
59         report->type= type;
60         report->typestr= wm_report_type_str(type);
61
62         len= strlen(message);
63         report->message= MEM_callocN(sizeof(char)*(len+1), "wmReportMessage");
64         memcpy(report->message, message, sizeof(char)*(len+1));
65
66         if(wmReportPrint)
67                 wm_print_report(report);
68         
69         BLI_addtail(&C->wm->reports, report);
70 }
71
72 void WM_reportf(bContext *C, int type, const char *format, ...)
73 {
74         wmReport *report;
75         va_list args;
76         char *message;
77         int len= 256, maxlen= 65536, retval;
78
79         if(!C->wm) {
80                 fprintf(stderr, "WM_report: can't report without windowmanager.\n");
81                 return;
82         }
83         if(type < wmReportLevel)
84                 return;
85
86         while(1) {
87                 message= MEM_callocN(sizeof(char)*len+1, "wmReportMessage");
88
89                 va_start(args, format);
90                 retval= vsnprintf(message, len, format, args);
91                 va_end(args);
92
93                 if(retval == -1) {
94                         /* -1 means not enough space, but on windows it may also mean
95                          * there is a formatting error, so we impose a maximum length */
96                         MEM_freeN(message);
97                         message= NULL;
98
99                         len *= 2;
100                         if(len > maxlen) {
101                                 fprintf(stderr, "WM_report message too long or format error.\n");
102                                 break;
103                         }
104                 }
105                 else if(retval > len) {
106                         /* in C99 the actual length required is returned */
107                         MEM_freeN(message);
108                         message= NULL;
109
110                         len= retval;
111                 }
112                 else
113                         break;
114         }
115
116         if(message) {
117                 report= MEM_callocN(sizeof(wmReport), "wmReport");
118                 report->type= type;
119                 report->typestr= wm_report_type_str(type);
120                 report->message= message;
121
122                 if(wmReportPrint)
123                         wm_print_report(report);
124
125                 BLI_addtail(&C->wm->reports, report);
126         }
127 }
128
129 void wm_report_free(wmReport *report)
130 {
131         MEM_freeN(report->message);
132         MEM_freeN(report);
133 }
134