1 /* Copyright (C) 2016 by Jeremy Tan */
2 /*
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are met:
5 
6  * Redistributions of source code must retain the above copyright notice, this
7  * list of conditions and the following disclaimer.
8 
9  * Redistributions in binary form must reproduce the above copyright notice,
10  * this list of conditions and the following disclaimer in the documentation
11  * and/or other materials provided with the distribution.
12 
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
14  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
16  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
17  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
18  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
19  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
21  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24 
25 #include <fontforge-config.h>
26 
27 /**
28  * @file ggdkdrawlogger.c
29  * @brief Implement logging and error handling functions
30  */
31 
32 #include "ggdkdrawP.h"
33 
34 #ifdef FONTFORGE_CAN_USE_GDK
35 #include <stdarg.h>
36 #include <stdio.h>
37 #include <string.h>
38 
39 static const char *unspecified_funct = "???";
40 static int log_level = LOGWARN;
41 
42 /**
43  * Initialise the logger
44  */
LogInit(void)45 void LogInit(void) {
46     const char *requested = getenv("GGDK_LOGLEVEL");
47 
48     if (requested) {
49         if (!strcmp(requested, "none")) {
50             log_level = LOGNONE;
51         } else if (!strcmp(requested, "error")) {
52             log_level = LOGERR;
53         } else if (!strcmp(requested, "warn")) {
54             log_level = LOGWARN;
55         } else if (!strcmp(requested, "info")) {
56             log_level = LOGINFO;
57         } else if (!strcmp(requested, "debug") || !strcmp(requested, "all")) {
58             log_level = LOGDEBUG;
59         }
60     }
61 }
62 
63 /**
64  * Print a message to stderr and log it via syslog. The message must be
65  * less than BUFSIZ characters long, or it will be truncated.
66  * @param level - Specify how severe the message is.
67 	If level is higher (less urgent) than the program's verbosity (see options.h) no message will be printed
68  * @param funct - String indicating the function name from which this function was called.
69 	If this is NULL, Log will show the unspecified_funct string instead
70  * @param file - Source file containing the function
71  * @param line - Line in the source file at which Log is called
72  * @param fmt - A format string
73  * @param ... - Arguments to be printed according to the format string
74  */
LogEx(int level,const char * funct,const char * file,int line,const char * fmt,...)75 void LogEx(int level, const char *funct, const char *file, int line, const char *fmt, ...) {
76     char buffer[BUFSIZ];
77     va_list va;
78 
79     if (level > log_level) {
80         return;
81     }
82 
83     va_start(va, fmt);
84     vsnprintf(buffer, BUFSIZ, fmt, va);
85     va_end(va);
86 
87     if (funct == NULL) {
88         funct = unspecified_funct;
89     }
90 
91     // Make a human readable severity string
92     const char *severity;
93     switch (level) {
94         case LOGERR:
95             severity = "ERROR";
96             break;
97         case LOGWARN:
98             severity = "WARNING";
99             break;
100         case LOGINFO:
101             severity = "INFO";
102             break;
103         default:
104             severity = "DEBUG";
105             break;
106     }
107 
108     GDateTime *now = g_date_time_new_now_local();
109     fprintf(stderr, "%02d:%02d:%02.3f %s: %s (%s:%d) - %s\n",
110             g_date_time_get_hour(now), g_date_time_get_minute(now),
111             g_date_time_get_seconds(now),
112             severity, funct, file, line, buffer);
113     fflush(stderr);
114     g_date_time_unref(now);
115 }
116 
GdkEventName(int code)117 const char *GdkEventName(int code) {
118     switch (code) {
119         case GDK_NOTHING:
120             return "GDK_NOTHING";
121             break;
122         case GDK_DELETE:
123             return "GDK_DELETE";
124             break;
125         case GDK_DESTROY:
126             return "GDK_DESTROY";
127             break;
128         case GDK_EXPOSE:
129             return "GDK_EXPOSE";
130             break;
131         case GDK_MOTION_NOTIFY:
132             return "GDK_MOTION_NOTIFY";
133             break;
134         case GDK_BUTTON_PRESS:
135             return "GDK_BUTTON_PRESS";
136             break;
137         case GDK_2BUTTON_PRESS:
138             return "GDK_2BUTTON_PRESS";
139             break;
140         case GDK_3BUTTON_PRESS:
141             return "GDK_3BUTTON_PRESS";
142             break;
143         case GDK_BUTTON_RELEASE:
144             return "GDK_BUTTON_RELEASE";
145             break;
146         case GDK_KEY_PRESS:
147             return "GDK_KEY_PRESS";
148             break;
149         case GDK_KEY_RELEASE:
150             return "GDK_KEY_RELEASE";
151             break;
152         case GDK_ENTER_NOTIFY:
153             return "GDK_ENTER_NOTIFY";
154             break;
155         case GDK_LEAVE_NOTIFY:
156             return "GDK_LEAVE_NOTIFY";
157             break;
158         case GDK_FOCUS_CHANGE:
159             return "GDK_FOCUS_CHANGE";
160             break;
161         case GDK_CONFIGURE:
162             return "GDK_CONFIGURE";
163             break;
164         case GDK_MAP:
165             return "GDK_MAP";
166             break;
167         case GDK_UNMAP:
168             return "GDK_UNMAP";
169             break;
170         case GDK_PROPERTY_NOTIFY:
171             return "GDK_PROPERTY_NOTIFY";
172             break;
173         case GDK_SELECTION_CLEAR:
174             return "GDK_SELECTION_CLEAR";
175             break;
176         case GDK_SELECTION_REQUEST:
177             return "GDK_SELECTION_REQUEST";
178             break;
179         case GDK_SELECTION_NOTIFY:
180             return "GDK_SELECTION_NOTIFY";
181             break;
182         case GDK_PROXIMITY_IN:
183             return "GDK_PROXIMITY_IN";
184             break;
185         case GDK_PROXIMITY_OUT:
186             return "GDK_PROXIMITY_OUT";
187             break;
188         case GDK_DRAG_ENTER:
189             return "GDK_DRAG_ENTER";
190             break;
191         case GDK_DRAG_LEAVE:
192             return "GDK_DRAG_LEAVE";
193             break;
194         case GDK_DRAG_MOTION:
195             return "GDK_DRAG_MOTION";
196             break;
197         case GDK_DRAG_STATUS:
198             return "GDK_DRAG_STATUS";
199             break;
200         case GDK_DROP_START:
201             return "GDK_DROP_START";
202             break;
203         case GDK_DROP_FINISHED:
204             return "GDK_DROP_FINISHED";
205             break;
206         case GDK_CLIENT_EVENT:
207             return "GDK_CLIENT_EVENT";
208             break;
209         case GDK_VISIBILITY_NOTIFY:
210             return "GDK_VISIBILITY_NOTIFY";
211             break;
212         case GDK_SCROLL:
213             return "GDK_SCROLL";
214             break;
215         case GDK_WINDOW_STATE:
216             return "GDK_WINDOW_STATE";
217             break;
218         case GDK_SETTING:
219             return "GDK_SETTING";
220             break;
221         case GDK_OWNER_CHANGE:
222             return "GDK_OWNER_CHANGE";
223             break;
224         case GDK_GRAB_BROKEN:
225             return "GDK_GRAB_BROKEN";
226             break;
227         case GDK_DAMAGE:
228             return "GDK_DAMAGE";
229             break;
230         case GDK_TOUCH_BEGIN:
231             return "GDK_TOUCH_BEGIN";
232             break;
233         case GDK_TOUCH_UPDATE:
234             return "GDK_TOUCH_UPDATE";
235             break;
236         case GDK_TOUCH_END:
237             return "GDK_TOUCH_END";
238             break;
239         case GDK_TOUCH_CANCEL:
240             return "GDK_TOUCH_CANCEL";
241             break;
242 #ifdef GGDKDRAW_GDK_3_20
243         case GDK_TOUCHPAD_SWIPE:
244             return "GDK_TOUCHPAD_SWIPE";
245             break;
246         case GDK_TOUCHPAD_PINCH:
247             return "GDK_TOUCHPAD_PINCH";
248             break;
249 #endif
250         case GDK_EVENT_LAST:
251             return "GDK_EVENT_LAST";
252             break;
253         default:
254             return "UNKNOWN";
255     }
256 }
257 
258 #endif // FONTFORGE_CAN_USE_GDK
259