Convert uses of XKeycodeToKeysym (deprecated) to XkbKeycodeToKeysym
[oweals/cde.git] / cde / programs / ttsnoop / DtTt.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 libraries 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 //%%  (c) Copyright 1993, 1994 Hewlett-Packard Company
24 //%%  (c) Copyright 1993, 1994 International Business Machines Corp.
25 //%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.
26 //%%  (c) Copyright 1993, 1994 Novell, Inc.
27 //%%  $XConsortium: DtTt.C /main/4 1996/03/19 10:47:59 barstow $
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <sys/wait.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36
37 #include <sstream>
38
39 #include <Xm/TextF.h>
40 #include <Dt/SpinBox.h>
41 #include <Dt/HelpDialog.h>
42 #include "tt_c++.h"
43 #include "DtTt.h"
44 #include "messageProps_ui.h"
45 #include "patternProps_ui.h"
46
47 static const char **    dtTtProcids             = 0;
48 static const void **    dtTtProcidClientDatums  = 0;
49 static unsigned int     dtTtProcidsCount        = 0;
50 static Tt_pattern *     dtTtPatterns            = 0;
51 static unsigned int     dtTtPatternsCount       = 0;
52 static Tt_message *     dtTtMessages            = 0;
53 static unsigned int     dtTtMessagesCount       = 0;
54 static Tt_pattern **    dtTtDtSessions          = 0;
55 static unsigned int     dtTtDtSessionsCount     = 0;
56 static Tt_pattern **    dtTtDtFiles             = 0;
57 static unsigned int     dtTtDtFilesCount        = 0;
58
59 int             _DtTtPatsNameKey        = (int) (long) DtTtNth;
60 extern Tt_pattern       snoopPat;
61
62 int
63 listGrow(
64         void **         pList,
65         unsigned int &  listCount,
66         size_t          elemSize
67 )
68 {
69         void *newList;
70         newList = realloc( *pList, (1 + listCount) * elemSize );
71         if (newList == 0) {
72                 return 0;
73         }
74         *pList = newList;
75         listCount++;
76         return 1;
77 }
78
79 XmString
80 DtTtStatusString(
81         Tt_status       status
82 )
83 {
84         char *s = tt_status_string( status );
85         XmString s2 = XmStringCreateLocalized( s );
86         tt_free( s );
87         return s2;
88 }
89
90 Tt_status
91 DtTtCreated(
92         DtTtType        type,
93         const void *    entity,
94         const void *    clientData
95 )
96 {
97         Tt_status status = tt_ptr_error( entity );
98         if ((tt_is_err( status )) || (entity == 0)) {
99                 return TT_OK;
100         }
101         switch (type) {
102                 char *proc;
103             case DTTT_PROCID:
104                 proc = strdup( (const char *)entity );
105                 if (proc == 0) {
106                         return TT_ERR_NOMEM;
107                 }
108                 if (! listAppend( dtTtProcids, dtTtProcidsCount, const char *,
109                                   proc ))
110                 {
111                         return TT_ERR_NOMEM;
112                 }
113                 dtTtProcidsCount--; // shared by both lists
114                 if (! listAppend( dtTtProcidClientDatums, dtTtProcidsCount,
115                                   const void *, clientData ))
116                 {
117                         return TT_ERR_NOMEM;
118                 }
119                 break;
120             case DTTT_MESSAGE:
121                 if (DtTtIndex( type, entity ) >= 0) {
122                         return TT_OK;
123                 }
124                 if (! listAppend( dtTtMessages, dtTtMessagesCount, Tt_message,
125                                   (const Tt_message)entity ))
126                 {
127                         return TT_ERR_NOMEM;
128                 }
129                 break;
130             case DTTT_PATTERN:
131                 if (DtTtIndex( type, entity ) >= 0) {
132                         return TT_OK;
133                 }
134                 if (! listAppend( dtTtPatterns, dtTtPatternsCount, Tt_pattern,
135                                   (const Tt_pattern)entity ))
136                 {
137                         return TT_ERR_NOMEM;
138                 }
139                 break;
140             case DTTT_PTYPE:
141             case DTTT_OTYPE:
142             case DTTT_OBJECT:
143             case DTTT_SESSION:
144             case DTTT_DTSESSION:
145             case DTTT_DTFILE:
146             case DTTT_OP:
147                 abort();
148                 break;
149         }
150         return TT_OK;
151 }
152
153 Tt_status
154 DtTtCreated(
155         DtTtType        type,
156         Tt_pattern *    entity,
157         const char *    name
158 )
159 {
160         if ((tt_is_err( tt_ptr_error( entity ) )) || (entity == 0)) {
161                 return TT_OK;
162         }
163         if ((tt_is_err( tt_ptr_error( name ) )) || (name == 0)) {
164                 return TT_OK;
165         }
166         switch (type) {
167             case DTTT_PROCID:
168             case DTTT_MESSAGE:
169             case DTTT_PATTERN:
170             case DTTT_PTYPE:
171             case DTTT_OTYPE:
172             case DTTT_OBJECT:
173             case DTTT_SESSION:
174             case DTTT_OP:
175                 abort();
176                 break;
177             case DTTT_DTSESSION:
178                 tt_pattern_user_set( *entity, _DtTtPatsNameKey,
179                                      strdup( name ));
180                 if (DtTtIndex( type, entity ) >= 0) {
181                         return TT_OK;
182                 }
183                 if (! listAppend( dtTtDtSessions, dtTtDtSessionsCount,
184                                   Tt_pattern *, (Tt_pattern *)entity ))
185                 {
186                         return TT_ERR_NOMEM;
187                 }
188                 break;
189             case DTTT_DTFILE:
190                 tt_pattern_user_set( *entity, _DtTtPatsNameKey,
191                                      strdup( name ));
192                 if (DtTtIndex( type, entity ) >= 0) {
193                         return TT_OK;
194                 }
195                 if (! listAppend( dtTtDtFiles, dtTtDtFilesCount,
196                                   Tt_pattern *, (Tt_pattern *)entity ))
197                 {
198                         return TT_ERR_NOMEM;
199                 }
200                 break;
201         }
202         while (*entity != 0) {
203                 DtTtCreated( DTTT_PATTERN, *entity );
204                 entity++;
205         }
206         return TT_OK;
207 }
208
209 void *
210 DtTtNth(
211         DtTtType        type,
212         int             n
213 )
214 {
215         switch (type) {
216             case DTTT_PROCID:
217                 if ((n < 0) || (n >= dtTtProcidsCount)) {
218                         return 0;
219                 }
220                 return (void *)dtTtProcids[ n ];
221             case DTTT_MESSAGE:
222                 if ((n < 0) || (n >= dtTtMessagesCount)) {
223                         return 0;
224                 }
225                 return dtTtMessages[ n ];
226             case DTTT_PATTERN:
227                 if ((n < 0) || (n >= dtTtPatternsCount)) {
228                         return 0;
229                 }
230                 return dtTtPatterns[ n ];
231             case DTTT_DTSESSION:
232                 if ((n < 0) || (n >= dtTtDtSessionsCount)) {
233                         return 0;
234                 }
235                 return dtTtDtSessions[ n ];
236             case DTTT_DTFILE:
237                 if ((n < 0) || (n >= dtTtDtFilesCount)) {
238                         return 0;
239                 }
240                 return dtTtDtFiles[ n ];
241             case DTTT_OP:
242                 return tttk_op_string( (Tttk_op)(n+1) );
243         }
244 }
245
246 void *
247 DtTtNthClientDatum(
248         DtTtType        type,
249         int             n
250 )
251 {
252         switch (type) {
253             case DTTT_PROCID:
254                 if ((n < 0) || (n >= dtTtProcidsCount)) {
255                         return 0;
256                 }
257                 return (void *)dtTtProcidClientDatums[ n ];
258             default:
259                 abort();
260                 return 0;
261         }
262 }
263
264 void
265 DtTtNthClientDatumSet(
266         DtTtType        type,
267         int             n,
268         const void *    clientData
269 )
270 {
271         switch (type) {
272             case DTTT_PROCID:
273                 if ((n < 0) || (n >= dtTtProcidsCount)) {
274                         return;
275                 }
276                 dtTtProcidClientDatums[ n ] = clientData;
277                 return;
278             default:
279                 abort();
280         }
281 }
282
283 int
284 DtTtIndex(
285         DtTtType        type,
286         const void *    entity
287 )
288 {
289         Tt_status status = tt_ptr_error( entity );
290         if ((tt_is_err( status )) || (entity == 0)) {
291                 return -1;
292         }
293         switch (type) {
294                 int i;
295             case DTTT_PROCID:
296                 for (i = dtTtProcidsCount - 1; i >= 0; i--) {
297                         if (strcmp( dtTtProcids[i], (char *)entity) == 0) {
298                                 return i;
299                         }
300                 }
301                 return -1;
302             case DTTT_MESSAGE:
303                 for (i = dtTtMessagesCount - 1; i >= 0; i--) {
304                         if (dtTtMessages[i] == entity) {
305                                 return i;
306                         }
307                 }
308                 return -1;
309             case DTTT_PATTERN:
310                 for (i = dtTtPatternsCount - 1; i >= 0; i--) {
311                         if (dtTtPatterns[i] == entity) {
312                                 return i;
313                         }
314                 }
315                 return -1;
316             case DTTT_DTSESSION:
317                 for (i = dtTtDtSessionsCount - 1; i >= 0; i--) {
318                         if (dtTtDtSessions[i] == entity) {
319                                 return i;
320                         }
321                 }
322                 return -1;
323             case DTTT_DTFILE:
324                 for (i = dtTtDtFilesCount - 1; i >= 0; i--) {
325                         if (dtTtDtFiles[i] == entity) {
326                                 return i;
327                         }
328                 }
329                 return -1;
330             case DTTT_OP:
331                 for (i = 1; i < TTDT_OP_LAST; i++) {
332                         if (0 == strcmp( tttk_op_string( (Tttk_op)i ),
333                                          (char *)entity ))
334                         {
335                                 return i;
336                         }
337                 }
338                 return -1;
339         }
340 }
341
342 Tt_status
343 DtTtDestroyed(
344         DtTtType        type,
345         const void *    entity
346 )
347 {
348         Tt_status status = tt_ptr_error( entity );
349         if ((tt_is_err( status )) || (entity == 0)) {
350                 return TT_OK;
351         }
352         switch (type) {
353                 int i, j;
354                 Tt_pattern *pats;
355             case DTTT_PROCID:
356                 for (i = dtTtProcidsCount - 1; i >= 0; i--) {
357                         if (strcmp( dtTtProcids[i], (char *)entity) == 0) {
358                                 break;
359                         }
360                 }
361                 if (i < 0) {
362                         return TT_WRN_NOTFOUND;
363                 }
364                 for (j = i; j < dtTtProcidsCount - 1; j++) {
365                         dtTtProcids[j] = dtTtProcids[j+1];
366                 }
367                 for (j = i; j < dtTtProcidsCount - 1; j++) {
368                         dtTtProcidClientDatums[j] =
369                                 dtTtProcidClientDatums[j+1];
370                 }
371                 dtTtProcidsCount--;
372                 break;
373             case DTTT_MESSAGE:
374                 for (i = dtTtMessagesCount - 1; i >= 0; i--) {
375                         if (dtTtMessages[i] == entity) {
376                                 break;
377                         }
378                 }
379                 if (i < 0) {
380                         return TT_WRN_NOTFOUND;
381                 }
382                 for (j = i; j < dtTtMessagesCount - 1; j++) {
383                         dtTtMessages[j] = dtTtMessages[j+1];
384                 }
385                 dtTtMessagesCount--;
386                 break;
387             case DTTT_PATTERN:
388                 if (snoopPat == entity) snoopPat = 0;
389                 for (i = dtTtPatternsCount - 1; i >= 0; i--) {
390                         if (dtTtPatterns[i] == entity) {
391                                 break;
392                         }
393                 }
394                 if (i < 0) {
395                         return TT_WRN_NOTFOUND;
396                 }
397                 for (j = i; j < dtTtPatternsCount - 1; j++) {
398                         dtTtPatterns[j] = dtTtPatterns[j+1];
399                 }
400                 dtTtPatternsCount--;
401                 break;
402             case DTTT_DTSESSION:
403                 for (i = dtTtDtSessionsCount - 1; i >= 0; i--) {
404                         if (dtTtDtSessions[i] == entity) {
405                                 break;
406                         }
407                 }
408                 if (i < 0) {
409                         return TT_WRN_NOTFOUND;
410                 }
411                 pats = (Tt_pattern *)entity;
412                 while (*pats != 0) {
413                         DtTtDestroyed( DTTT_PATTERN, *pats );
414                         pats++;
415                 }
416                 for (j = i; j < dtTtDtSessionsCount - 1; j++) {
417                         dtTtDtSessions[j] = dtTtDtSessions[j+1];
418                 }
419                 dtTtDtSessionsCount--;
420                 break;
421             case DTTT_DTFILE:
422                 for (i = dtTtDtFilesCount - 1; i >= 0; i--) {
423                         if (dtTtDtFiles[i] == entity) {
424                                 break;
425                         }
426                 }
427                 if (i < 0) {
428                         return TT_WRN_NOTFOUND;
429                 }
430                 pats = (Tt_pattern *)entity;
431                 while (*pats != 0) {
432                         DtTtDestroyed( DTTT_PATTERN, *pats );
433                         pats++;
434                 }
435                 for (j = i; j < dtTtDtFilesCount - 1; j++) {
436                         dtTtDtFiles[j] = dtTtDtFiles[j+1];
437                 }
438                 dtTtDtFilesCount--;
439                 break;
440         }
441         return TT_OK;
442 }
443
444 Tt_status
445 DtTtSetLabel(
446         Widget labelWidget,
447         const char *string
448 )
449 {
450     if (labelWidget == 0) {
451             return TT_OK;
452     }
453     XmString labelXmString = XmStringCreateLocalized( (String)string );
454     XtVaSetValues( labelWidget, XmNlabelString, labelXmString, NULL );
455     XmStringFree( labelXmString );
456     return TT_OK;
457 }
458
459 Tt_status
460 DtTtSetLabel(
461         Widget labelWidget,
462         const char *func,
463         void *val
464 )
465 {
466     Tt_status status = tt_ptr_error( val );
467     std::ostringstream errStream;
468     errStream << func << " = " << val << " (" << status << ")" << ends;
469     DtTtSetLabel( labelWidget, errStream.str().c_str() );
470     return status;
471 }
472
473 Tt_status
474 DtTtSetLabel(
475         Widget labelWidget,
476         const char *func,
477         Tt_status status
478 )
479 {
480     std::ostringstream errStream;
481     errStream << func << " = " << status << ends;
482     DtTtSetLabel( labelWidget, errStream.str().c_str() );
483     return status;
484 }
485
486 int
487 DtTtSetLabel(
488         Widget labelWidget,
489         const char *func,
490         int returnVal
491 )
492 {
493     std::ostringstream errStream;
494     errStream << func << " = " << returnVal << ends;
495     DtTtSetLabel( labelWidget,
496                   const_cast<char *>(errStream.str().c_str()) );
497     return returnVal;
498 }
499
500
501 static XmString *
502 _DtTtChoices(
503         Tt_pattern **   pPats,
504         int             count
505 )
506 {
507         // XXX when to free?
508         XmString *items = (XmString *)XtMalloc( count * sizeof( XmString ));
509         if (items == 0) {
510                 return 0;
511         }
512         for (int i = 0; i < count; i++) {
513                 std::ostringstream itemStream;
514                 itemStream << (void *)pPats[ i ];
515                 char *name = (char *)
516                         tt_pattern_user( *pPats[ i ], _DtTtPatsNameKey );
517                 if (! tt_is_err( tt_ptr_error( name ))) {
518                         itemStream << " " << name;
519                         tt_free( name );
520                 }
521                 itemStream << ends;
522                 items[ i ] =
523                     XmStringCreateLocalized(const_cast<char *>(itemStream.str().c_str()));
524         }
525         return items;
526 }
527
528 XmString *
529 _DtTtChoices(
530         DtTtType type,
531         int *    itemCount
532 )
533 {
534         *itemCount = 0;
535         switch (type) {
536                 XmString *items;
537                 int i;
538                 int opCount;
539             case DTTT_PROCID:
540                 items = (XmString *)
541                         XtMalloc( dtTtProcidsCount * sizeof( XmString ));
542                 if (items == 0) {
543                         return 0;
544                 }
545                 *itemCount = dtTtProcidsCount;
546                 for (i = 0; i < dtTtProcidsCount; i++) {
547                         items[ i ] = XmStringCreateLocalized(
548                                         (String)dtTtProcids[ i ] );
549                 }
550                 return items;
551             case DTTT_MESSAGE:
552                 items = (XmString *)
553                         XtMalloc( dtTtMessagesCount * sizeof( XmString ));
554                 if (items == 0) {
555                         return 0;
556                 }
557                 *itemCount = dtTtMessagesCount;
558                 for (i = 0; i < dtTtMessagesCount; i++) {
559                         std::ostringstream itemStream;
560                         itemStream << (void *)dtTtMessages[ i ];
561                         char *op = tt_message_op( dtTtMessages[ i ] );
562                         if (! tt_is_err( tt_ptr_error( op ))) {
563                                 itemStream << " " << op;
564                                 tt_free( op );
565                         }
566                         char *id = tt_message_id( dtTtMessages[ i ] );
567                         if (! tt_is_err( tt_ptr_error( id ))) {
568                                 itemStream << " " << id;
569                                 tt_free( id );
570                         }
571                         itemStream << ends;
572                         items[ i ] =
573                             XmStringCreateLocalized(const_cast<char *>(itemStream.str().c_str()));
574                 }
575                 return items;
576             case DTTT_PATTERN:
577                 items = (XmString *)
578                         XtMalloc( dtTtPatternsCount * sizeof( XmString ));
579                 if (items == 0) {
580                         return 0;
581                 }
582                 *itemCount = dtTtPatternsCount;
583                 for (i = 0; i < dtTtPatternsCount; i++) {
584                         std::ostringstream itemStream;
585                         itemStream << (void *)dtTtPatterns[ i ] << ends;
586                         items[ i ] = XmStringCreateLocalized(
587                             const_cast<char *>(itemStream.str().c_str()) );
588                 }
589                 return items;
590             case DTTT_DTSESSION:
591                 *itemCount = dtTtDtSessionsCount;
592                 return _DtTtChoices( dtTtDtSessions, dtTtDtSessionsCount );
593             case DTTT_DTFILE:
594                 *itemCount = dtTtDtFilesCount;
595                 return _DtTtChoices( dtTtDtFiles, dtTtDtFilesCount );
596             case DTTT_OP:
597                 // XXX when to free? ditto for each case
598                 opCount = ((int)TTDT_OP_LAST) - 1;
599                 items = (XmString *)
600                         XtMalloc( opCount * sizeof( XmString ));
601                 if (items == 0) {
602                         return 0;
603                 }
604                 *itemCount = opCount;
605                 for (i = 1; i <= opCount; i++) {
606                         items[ i-1 ] = XmStringCreateLocalized(
607                                         (String)tttk_op_string( (Tttk_op)i ));
608                 }
609                 return items;
610         }
611 }
612
613 #if defined(aix)
614 #define AIX_CONST_STRING        (char *)
615 #else
616 #define AIX_CONST_STRING
617 #endif
618
619 void
620 _DtOpen(
621         Widget          label,
622         const char *    cmd,
623         const char *    tempnamTemplate
624 )
625 {
626     char *file = tempnam( 0, AIX_CONST_STRING tempnamTemplate );
627     std::ostringstream cmdStream;
628     cmdStream << cmd << " > " << file << ends;
629     int sysStat = system( cmdStream.str().c_str() );
630     if (! WIFEXITED( sysStat )) {
631             std::ostringstream func;
632             func << "system( \"" << cmdStream.str() << "\" )" << ends;
633             DtTtSetLabel( label, func.str().c_str(), sysStat );
634             return;
635     }
636     if (WEXITSTATUS( sysStat ) != 0) {
637         DtTtSetLabel( label, cmdStream.str().c_str(), WEXITSTATUS( sysStat ));
638             return;
639     }
640     _DtOpen( label, file );
641 }
642
643 void
644 _DtOpen(
645         Widget          label,
646         const char *    file
647 )
648 {
649     std::ostringstream labelStream;
650     labelStream << "dtaction Open " << file << ends;
651     DtTtSetLabel( label, labelStream.str().c_str() );
652
653     std::ostringstream cmd;
654     cmd << "( unset TT_TRACE_SCRIPT; if dtaction Open " << file
655         << "; then :; else textedit " << file << "; fi; sleep 600; rm -f "
656         << file << " ) &" << ends;
657     system( cmd.str().c_str() );
658 }
659
660 void
661 _DtOpen(
662         Widget          label,
663         void *          buf,
664         size_t          len,
665         const char *    tempnamTemplate
666 )
667 {
668     char *file = tempnam( 0, AIX_CONST_STRING tempnamTemplate );
669     int fd = open( file, O_WRONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR );
670     if (write( fd, buf, len ) < 0) {
671             DtTtSetLabel( label, file, errno );
672             return;
673     }
674     close( fd );
675     _DtOpen( label, file );
676 }
677
678 void
679 _DtMan(
680         Widget          label,
681         const char *    topic
682 )
683 {
684     std::ostringstream labelStream;
685     labelStream << "dtaction Dtmanpageview " << topic << ends;
686     DtTtSetLabel( label, labelStream.str().c_str() );
687
688     std::ostringstream cmd;
689     cmd << "unset TT_TRACE_SCRIPT; if dtaction Dtmanpageview " << topic
690         << "; then :; else cmdtool -c man " << topic << "; fi &" << ends;
691     system( cmd.str().c_str() );
692 }
693
694 Boolean
695 _DtCanHelp(
696         const char *topics
697 )
698 {
699         if (topics == 0) return False;
700         if (strchr( topics, ' ' ) != 0) {
701                 // Must not be a list of man pages
702                 return False;
703         }
704         return True;
705 }
706
707 Boolean
708 _DtHelped(
709         Widget helpDialog
710 )
711 {
712         char *topics;
713         XtVaGetValues( helpDialog, DtNstringData, &topics, NULL );
714         if (! _DtCanHelp( topics )) {
715                 return False;
716         }
717         char *newTopics = strdup( topics );
718         const char *whiteSpace = "(12345689) \t:-,.*\n";
719         const char *topic = strtok( newTopics, whiteSpace );
720         while (topic != 0) {
721                 _DtMan( 0, topic );
722                 topic = strtok( 0, whiteSpace );
723         }
724         free( newTopics );
725         return True;
726 }