Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / DtTerm / TermPrim / TermPrimDebug.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 #ifndef lint
24 #ifdef  VERBOSE_REV_INFO
25 static char rcs_id[] = "$XConsortium: TermPrimDebug.c /main/4 1996/11/21 19:58:15 drk $";
26 #endif  /* VERBOSE_REV_INFO */
27 #endif  /* lint */
28
29 /*                                                                      *
30  * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company               *
31  * (c) Copyright 1993, 1994, 1996 International Business Machines Corp. *
32  * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc.                *
33  * (c) Copyright 1993, 1994, 1996 Novell, Inc.                          *
34  * (c) Copyright 1996 Digital Equipment Corporation.                    *
35  * (c) Copyright 1996 FUJITSU LIMITED.                                  *
36  * (c) Copyright 1996 Hitachi.                                          *
37  */
38
39 #include <stdio.h>
40 #include <unistd.h>
41 #include <stdlib.h>
42 #include <varargs.h>
43 #include "TermHeader.h"
44 #include "TermPrimDebug.h"
45 #include <signal.h>
46
47 #define X_INCLUDE_STRING_H
48 #define XOS_USE_NO_LOCKING
49 #include <X11/Xos_r.h>
50
51 unsigned char *debugLevel[256] = { NULL }; /* debug level               */
52
53 #ifdef  BBA
54 #pragma BBA_IGNORE
55 #endif  /*BBA*/
56 int
57 isDebugFSet(int c, int f)
58 {
59     int i;
60     
61     _DtTermProcessLock();
62     i = ((f < _TERM_MAX_DEBUG_FLAG) ?
63             debugLevel[c % 256] &&
64             (debugLevel[c % 256][__TERM_DEBUG_BYTE(f)] & __TERM_DEBUG_BIT(f)) :
65             0);
66     _DtTermProcessUnlock();
67     return(i);
68 }
69
70 #ifdef  BBA
71 #pragma BBA_IGNORE
72 #endif  /*BBA*/
73 static
74 void
75 catchExit(void)
76 {
77     int a;
78     int b;
79
80     a = 1;
81     b = a;
82     a = b;
83     return;
84 }
85
86 typedef struct _argArray {
87     char *str;
88     struct _argArray *next;
89 } argArray;
90
91 #ifdef  BBA
92 #pragma BBA_IGNORE
93 #endif  /*BBA*/
94 void
95 setDebugFlags(char *c1)
96 {
97     argArray argHead;
98     argArray *argPtr;
99     int i1;
100     int i2;
101     char *c2;
102     char *c3;
103     char *charList;
104     char *flagList;
105     char charArray[BUFSIZ];
106     unsigned char theseFlags[_TERM_DEBUG_NUM_BYTES];
107     char startChar;
108     char endChar;
109     int startFlag;
110     int endFlag;
111     Boolean isValid;
112     static Boolean catchExitRegistered = False;
113     _Xstrtokparams strtok_buf;
114
115     /* ignore null or empty strings... */
116     if (!c1 || !*c1) {
117         return;
118     }
119
120     /* register our catchExit() function... */
121     _DtTermProcessLock();
122     if (!catchExitRegistered) {
123         (void) atexit(catchExit);
124         catchExitRegistered = True;
125     }
126
127     /* strtok out c1...
128      */
129
130     /* don't destroy the original string... */
131     c2 = malloc(strlen(c1) + 1);
132     (void) strcpy(c2, c1);
133
134
135     argHead.next = (argArray *) 0;
136     argPtr = &argHead;
137     while (c3 = _XStrtok(c2, " \t\n", strtok_buf)) {
138         /* null out c2 so we won't restart strtok... */
139         c2 = (char *) 0;
140         argPtr->next = (argArray *) malloc(sizeof(argArray));
141         argPtr = argPtr->next;
142         argPtr->next = (argArray *) 0;
143         argPtr->str = c3;
144     }
145
146     /* run through the linked list and parse each string... */
147     for (argPtr = argHead.next; argPtr; argPtr = argPtr->next) {
148         charList = argPtr->str;
149         flagList = (char *) 0;
150         if (c2 = strchr(argPtr->str, ':')) {
151             /* null out the ':'... */
152             *c2++ = '\0';
153             flagList = c2;
154         }
155
156         /* fill out the char array... */
157         for (c2 = charArray; *charList; ) {
158             isValid = False;
159             if (isalpha(*charList)) {
160                 isValid = True;
161                 startChar = *charList++;
162             } else {
163                 startChar = 'A';
164             }
165
166             if (*charList == '-') {
167                 isValid = True;
168                 (void) charList++;
169                 if (isalpha(*charList)) {
170                     endChar = *charList++;
171                 } else {
172                     endChar = 'z';
173                 }
174             } else {
175                 endChar = startChar;
176             }
177
178             if (isValid) {
179                 while (startChar <= endChar) {
180                     *c2++ = startChar++;
181                 }
182                 /* null term... */
183                 *c2 = '\0';
184             } else {
185                 break;
186             }
187         }
188
189         /* fill out theseFlags... */
190         (void) memset(theseFlags, '\0', sizeof(theseFlags));
191         if (!flagList || !*flagList) {
192             flagList = strdup("-");
193         }
194
195         c3 = flagList;
196         while (flagList = _XStrtok(c3, ",", strtok_buf)) {
197             /* null out c3 so we won't restart strtok... */
198             c3 = (char *) 0;
199             if (!flagList || !*flagList) {
200                 continue;
201             }
202             if (isdigit(*flagList)) {
203                 startFlag = strtol(flagList, &flagList, 0);
204             } else {
205                 startFlag = 0;
206             }
207             endFlag = startFlag;
208
209             if (*flagList == '-') {
210                 /* we have a range... */
211                 /* skip over the '-'... */
212                 (void) flagList++;
213                 if (isdigit(*flagList)) {
214                     endFlag = strtol(flagList, (char **) 0, 0);
215                 } else {
216                     endFlag = _TERM_MAX_DEBUG_FLAG - 1;
217                 }
218             }
219
220             if (startFlag < 0) {
221                 startFlag = 0;
222             }
223             if (endFlag > (_TERM_MAX_DEBUG_FLAG - 1)) {
224                 endFlag = _TERM_MAX_DEBUG_FLAG - 1;
225             }
226             for (; startFlag <= endFlag; startFlag++) {
227                 theseFlags[__TERM_DEBUG_BYTE(startFlag)] |=
228                         __TERM_DEBUG_BIT(startFlag);
229             }
230         }
231
232         /* now run through the the char array and or in these flags... */
233         for (c2 = charArray; *c2; c2++) {
234             if (isalpha(*c2)) {
235                 if (!debugLevel[*c2]) {
236                     debugLevel[*c2] =
237                             (unsigned char *) malloc(_TERM_DEBUG_NUM_BYTES);
238                     (void) memset(debugLevel[*c2], '\0', _TERM_DEBUG_NUM_BYTES);
239                 }
240                 for (i1 = 0; i1 < _TERM_DEBUG_NUM_BYTES; i1++) {
241                     debugLevel[*c2][i1] |= theseFlags[i1];
242                 }
243             }
244         }
245     }
246
247     /* dump out a list of set flags... */
248     if (isDebugFSet('v', 0)) {
249         for (i1 = 0; i1 < 256; i1++) {
250             if (debugLevel[i1]) {
251                 (void) fprintf(stderr, "debug flag '%c'  ", i1);
252                 for (i2 = 0; i2 < _TERM_MAX_DEBUG_FLAG; i2++) {
253                     if (i2 > 0 && (0 == i2 % 50)) {
254                         (void) fputs("\n                ", stderr);
255                     }
256                     if (debugLevel[i1][__TERM_DEBUG_BYTE(i2)] &
257                             __TERM_DEBUG_BIT(i2)) {
258                         (void) putc('X', stderr);
259                     } else {
260                         (void) putc('.', stderr);
261                     }
262                 }
263                 (void) putc('\n', stderr);
264             }
265         }
266     }
267     _DtTermProcessUnlock();
268 }
269
270 static Boolean timedOut;
271
272 #ifdef  BBA
273 #pragma BBA_IGNORE
274 #endif  /*BBA*/
275 /*ARGSUSED*/
276 static void
277 ding(int sig)
278 {
279     timedOut = True;
280 }
281
282 #ifdef  BBA
283 #pragma BBA_IGNORE
284 #endif  /*BBA*/
285 void
286 shortSleep(int msec)
287 {
288     struct sigaction action;
289     struct sigaction oldAction;
290     sigset_t sigset;
291     sigset_t oldSigset;
292     struct itimerval itime;
293     struct itimerval oldItime;
294
295     _DtTermProcessLock();
296     timedOut = False;
297
298     /* block SIGALRM... */
299     (void) sigemptyset(&sigset);
300     (void) sigaddset(&sigset, SIGALRM);
301     (void) sigprocmask(SIG_BLOCK, &sigset, &oldSigset);
302
303     /* set up a singnal handler for SIGALRM... */
304     action.sa_handler = ding;
305     action.sa_flags = 0;
306     (void) sigemptyset(&action.sa_mask);
307     (void) sigaction(SIGALRM, &action, &oldAction);
308
309     /* set an alarm... */
310     timerclear(&itime.it_interval);
311     itime.it_value.tv_usec = msec % 1000000;
312     itime.it_value.tv_sec = msec / 1000000;
313     (void) setitimer(ITIMER_REAL, &itime, &oldItime);
314
315     /* unblock SIGALRM and wait for a signal... */
316     (void) sigprocmask(SIG_BLOCK, (sigset_t *) 0, &sigset);
317     (void) sigdelset(&sigset, SIGALRM);
318     while (!timedOut) {
319         sigsuspend(&sigset);
320     }
321
322     /* restore old handler... */
323     (void) sigaction(SIGALRM, &oldAction, (struct sigaction *) 0);
324
325     /* restore old signal mask... */
326     (void) sigprocmask(SIG_SETMASK, &oldSigset, (sigset_t *) 0);
327     _DtTermProcessUnlock();
328 }
329
330 static FILE *timeStampFile = (FILE *) 0;
331
332 #ifdef  BBA
333 #pragma BBA_IGNORE
334 #endif  /*BBA*/
335 void
336 timeStamp(char *msg)
337 {
338     struct timeval tv;
339     struct timezone tz;
340
341     _DtTermProcessLock();
342     if (!timeStampFile) {
343         char *c;
344         char buffer[BUFSIZ];
345
346         if (!(c = getenv("timeStampFileName"))) {
347             (void) sprintf(buffer, "timeStamp-%d", getpid());
348             c = buffer;
349         }
350
351         if (!(timeStampFile = fopen(c, "a"))) {
352             _DtTermProcessUnlock();
353             return;
354         }
355
356         (void) setvbuf(timeStampFile, (char *) 0, _IOLBF, 0);
357     }
358     _DtTermProcessUnlock();
359
360     (void) gettimeofday(&tv, &tz);
361     (void) fprintf(timeStampFile, "%lu %ld %s\n", tv.tv_sec, tv.tv_usec,
362             (msg && *msg) ? msg : "");
363 }
364
365 typedef struct {
366     char                 *string;
367     int                   value;
368 } enumName;
369
370 static enumName eventTypes[] = {
371     {"KeyPress",                2},
372     {"KeyRelease",              3},
373     {"ButtonPress",             4},
374     {"ButtonRelease",           5},
375     {"MotionNotify",            6},
376     {"EnterNotify",             7},
377     {"LeaveNotify",             8},
378     {"FocusIn",                 9},
379     {"FocusOut",                10},
380     {"KeymapNotify",            11},
381     {"Expose",                  12},
382     {"GraphicsExpose",          13},
383     {"NoExpose",                14},
384     {"VisibilityNotify",        15},
385     {"CreateNotify",            16},
386     {"DestroyNotify",           17},
387     {"UnmapNotify",             18},
388     {"MapNotify",               19},
389     {"MapRequest",              20},
390     {"ReparentNotify",          21},
391     {"ConfigureNotify",         22},
392     {"ConfigureRequest",        23},
393     {"GravityNotify",           24},
394     {"ResizeRequest",           25},
395     {"CirculateNotify",         26},
396     {"CirculateRequest",        27},
397     {"PropertyNotify",          28},
398     {"SelectionClear",          29},
399     {"SelectionRequest",        30},
400     {"SelectionNotify",         31},
401     {"ColormapNotify",          32},
402     {"ClientMessage",           33},
403     {"MappingNotify",           34},
404     {"LASTEvent",               35},
405     {NULL},
406 };
407
408 static enumName notifyModes[] = {
409     {"NotifyNormal",            0},
410     {"NotifyGrab",              1},
411     {"NotifyUngrab",            2},
412     {"NotifyWhileGrabbed",      3},
413     {NULL},
414 };
415
416 static enumName notifyDetails[] = {
417     {"NotifyAncestor",          0},
418     {"NotifyVirtual",           1},
419     {"NotifyInferior",          2},
420     {"NotifyNonlinear",         3},
421     {"NotifyNonlinearVirtual",  4},
422     {"NotifyPointer",           5},
423     {"NotifyPointerRoot",       6},
424     {"NotifyDetailNone",        7},
425     {NULL},
426 };
427
428 static enumName boolTypes[] = {
429     {"True",                    1},
430     {"False",                   0},
431     {NULL},
432 };
433
434 static char *
435 enumToName
436 (
437     enumName             *list,
438     int                   value
439 )
440 {
441     int                   i1;
442     char                  buffer[BUFSIZ];
443     static char          *retBuffer = (char *) 0;
444
445     for (i1 = 0; list[i1].string; i1++) {
446         if (list[i1].value == value) {
447             return(list[i1].string);
448         }
449     }
450     (void) sprintf(buffer, "Unknown Value %d", value);
451     retBuffer = realloc(retBuffer, strlen(buffer));
452     (void) strcpy(retBuffer, buffer);
453     return(retBuffer);
454 }
455
456 void
457 _DtTermPrimDebugDumpEvent
458 (
459     FILE                 *f,
460     Widget                w,
461     XEvent               *ev
462 )
463 {
464     _DtTermProcessLock();
465     (void) fprintf(f, ">>  widget: name=\"%s\"  widget=0x%lx  window=0x%lx\n",
466             XtName(w), w, XtWindow(w));
467     (void) fprintf(f, ">> event {\n");
468     (void) fprintf(f, ">>     type=%s;\n",
469             enumToName(eventTypes, ev->xany.type));
470     (void) fprintf(f, ">>     serial=%lu\n", ev->xany.serial);
471     (void) fprintf(f, ">>     send_event=%s\n",
472             enumToName(boolTypes, ev->xany.send_event));
473     (void) fprintf(f, ">>     display=0x%lx\n", ev->xany.display);
474     (void) fprintf(f, ">>     window=0x%lx\n", ev->xany.window);
475     switch (ev->type) {
476     case EnterNotify:
477     case LeaveNotify:
478         (void) fprintf(f, ">>     root=0x%lx\n", ev->xcrossing.root);
479         (void) fprintf(f, ">>     subwindow=0x%lx\n", ev->xcrossing.subwindow);
480         (void) fprintf(f, ">>     mode=%s\n",
481                 enumToName(notifyModes, ev->xcrossing.mode));
482         (void) fprintf(f, ">>     detail=%s\n",
483                 enumToName(notifyDetails, ev->xcrossing.detail));
484         (void) fprintf(f, ">>     focus=%s\n",
485                 enumToName(boolTypes, ev->xcrossing.focus));
486         break;
487
488     case FocusIn:
489     case FocusOut:
490         (void) fprintf(f, ">>     mode=%s\n",
491                 enumToName(notifyModes, ev->xcrossing.mode));
492         (void) fprintf(f, ">>     detail=%s\n",
493                 enumToName(notifyDetails, ev->xcrossing.detail));
494         break;
495     }
496     (void) fprintf(f, ">> }\n");
497     _DtTermProcessUnlock();
498 }