Fixed poor handling of RCS logs by last CVS checkin
[dyninst.git] / paradyn / src / UIthread / whereAxisTcl.C
1 /*
2  * Copyright (c) 1996-1999 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // whereAxisTcl.C
43 // Ariel Tamches
44
45 // Implementations of new commands and tk bindings related to the where axis.
46
47 /* $Log: whereAxisTcl.C,v $
48 /* Revision 1.13  1999/03/12 22:59:37  pcroth
49 /* Fixed poor handling of RCS logs by last CVS checkin
50 /*
51  * Revision 1.12  1999/03/03 18:16:19  pcroth
52  * Updated to support Windows NT as a front-end platform
53  * Changes made to X code, to use Tcl analogues when appropriate
54  * Also changed in response to modifications in thread library and igen output.
55  *
56  * Revision 1.11  1997/01/15 00:14:10  tamches
57  * removed references to getCurrent() method of class abstraction
58  *
59  * Revision 1.10  1996/08/16 21:07:48  tamches
60  * updated copyright for release 1.1
61  *
62  * Revision 1.9  1996/08/05 07:31:42  tamches
63  * update for tcl 7.5
64  *
65  * Revision 1.8  1996/04/01 22:34:35  tamches
66  * added whereAxisVisibilityCallbackCommand
67  *
68  * Revision 1.7  1996/01/09 23:56:19  tamches
69  * added whereAxisDrawTipsCallback
70  *
71  * Revision 1.6  1995/10/17 22:22:44  tamches
72  * abstractions is no longer a templated type.
73  * Other minor changes corresponding to new where axis commits.
74  *
75  * Revision 1.5  1995/09/20 01:30:36  tamches
76  * File size reduced by using some utilities in the new tkTools.C file
77  *
78  * Revision 1.4  1995/08/04  19:19:25  tamches
79  * Commented out some cout statements that are for debugging only.
80  *
81  * Revision 1.3  1995/07/24  21:37:37  tamches
82  * better existsCurrent() error checking.
83  * Implemented alt-freescroll feature
84  *
85  * Revision 1.2  1995/07/18  03:41:27  tamches
86  * Added ctrl-double-click feature for selecting/unselecting an entire
87  * subtree (nonrecursive).  Added a "clear all selections" option.
88  * Selecting the root node now selects the entire program.
89  *
90  * Revision 1.1  1995/07/17  04:59:12  tamches
91  * First version of the new where axis
92  *
93  */
94
95 #ifndef PARADYN
96 // The test program has "correct" -I paths already set
97 #include "DMinclude.h" // for resourceHandle
98 #else
99 #include "paradyn/src/DMthread/DMinclude.h" // for resourceHandle
100 #endif
101
102 #include "abstractions.h"
103 #include "whereAxisTcl.h"
104 #include "tkTools.h"
105
106 // Here is the main where axis global variable:
107 abstractions *theAbstractions;
108
109 extern bool haveSeenFirstGoodWhereAxisWid; // test.C
110 extern bool tryFirstGoodWhereAxisWid(Tcl_Interp *, Tk_Window); // test.C
111
112 void whereAxisWhenIdleDrawRoutine(ClientData cd) {
113    assert(haveSeenFirstGoodWhereAxisWid);
114
115    const bool doubleBuffer = (bool)cd;
116
117 #ifdef PARADYN
118    const bool isXsynchOn = false;
119 #else
120    extern bool xsynchronize;
121    const bool isXsynchOn = xsynchronize;
122 #endif
123
124    theAbstractions->drawCurrent(doubleBuffer, isXsynchOn);
125 }
126 tkInstallIdle whereAxisDrawWhenIdle(&whereAxisWhenIdleDrawRoutine);
127
128 void initiateWhereAxisRedraw(Tcl_Interp *, bool doubleBuffer) {
129    whereAxisDrawWhenIdle.install((ClientData)doubleBuffer);
130 }
131
132 int whereAxisResizeCallbackCommand(ClientData, Tcl_Interp *interp,
133                                    int, char **) {
134    if (!tryFirstGoodWhereAxisWid(interp, Tk_MainWindow(interp)))
135       return TCL_ERROR;
136
137    if (theAbstractions->existsCurrent()) {
138       theAbstractions->resizeCurrent();
139       initiateWhereAxisRedraw(interp, true); // true-->use double-buffering
140    }
141
142    return TCL_OK;
143 }
144
145 int whereAxisExposeCallbackCommand(ClientData, Tcl_Interp *interp,
146                                    int argc, char **argv) {
147    if (!tryFirstGoodWhereAxisWid(interp, Tk_MainWindow(interp)))
148       return TCL_ERROR;
149
150    assert(argc == 2);
151
152    const int count = atoi(argv[1]); // Xevent count field (we should only redraw if 0)
153
154    if (theAbstractions->existsCurrent() && count==0)
155       initiateWhereAxisRedraw(interp, true); // true --> double buffer
156
157    return TCL_OK;
158 }
159
160 int whereAxisVisibilityCallbackCommand(ClientData, Tcl_Interp *interp,
161                                        int argc, char **argv) {
162    if (!tryFirstGoodWhereAxisWid(interp, Tk_MainWindow(interp)))
163       return TCL_ERROR;
164
165    assert(argc == 2);
166
167    char *newVisibility = argv[1];
168
169    if (0==strcmp(newVisibility, "VisibilityUnobscured"))
170       theAbstractions->makeVisibilityUnobscured();
171    else if (0==strcmp(newVisibility, "VisibilityPartiallyObscured"))
172       theAbstractions->makeVisibilityPartiallyObscured();
173    else if (0==strcmp(newVisibility, "VisibilityFullyObscured"))
174       theAbstractions->makeVisibilityFullyObscured();
175    else {
176       cerr << "unrecognized visibility " << newVisibility << endl;
177       return TCL_ERROR;
178    }
179
180    return TCL_OK;
181 }
182
183 int whereAxisSingleClickCallbackCommand(ClientData, Tcl_Interp *,
184                                         int argc, char **argv) {
185    assert(haveSeenFirstGoodWhereAxisWid);
186
187    assert(argc == 3);
188    const int x = atoi(argv[1]);
189    const int y = atoi(argv[2]);
190
191    if (theAbstractions->existsCurrent())
192       theAbstractions->processSingleClick(x, y);
193
194    return TCL_OK;
195 }
196
197 int whereAxisDoubleClickCallbackCommand(ClientData, Tcl_Interp *interp,
198                                         int argc, char **argv) {
199    assert(haveSeenFirstGoodWhereAxisWid);
200    assert(argc==3);
201
202    const int x = atoi(argv[1]);
203    const int y = atoi(argv[2]);
204
205    if (theAbstractions->existsCurrent()) {
206       bool needToRedrawAll=theAbstractions->processDoubleClick(x, y);
207       if (needToRedrawAll)
208          initiateWhereAxisRedraw(interp, true); // true--> use double buffer
209    }
210
211    return TCL_OK;
212 }
213
214 int whereAxisShiftDoubleClickCallbackCommand(ClientData, Tcl_Interp *interp,
215                                              int argc, char **argv) {
216    assert(haveSeenFirstGoodWhereAxisWid);
217    assert(argc == 3);
218
219    const int x = atoi(argv[1]);
220    const int y = atoi(argv[2]);
221
222    if (theAbstractions->existsCurrent()) {
223       bool needToRedrawAll=theAbstractions->processShiftDoubleClick(x, y);
224  
225       if (needToRedrawAll)
226          initiateWhereAxisRedraw(interp, true);
227    }
228
229    return TCL_OK;
230 }
231
232 int whereAxisCtrlDoubleClickCallbackCommand(ClientData, Tcl_Interp *interp,
233                                             int argc, char **argv) {
234    assert(haveSeenFirstGoodWhereAxisWid);
235
236    assert(argc==3);
237    const int x = atoi(argv[1]);
238    const int y = atoi(argv[2]);
239
240    if (theAbstractions->existsCurrent()) {
241       bool needToRedrawAll=theAbstractions->processCtrlDoubleClick(x, y);
242  
243       if (needToRedrawAll)
244          initiateWhereAxisRedraw(interp, true);
245    }
246
247    return TCL_OK;
248 }
249
250 int whereAxisNewVertScrollPositionCommand(ClientData, Tcl_Interp *interp,
251                                           int argc, char **argv) {
252    assert(haveSeenFirstGoodWhereAxisWid);
253
254    // The arguments will be one of:
255    // 1) moveto [fraction]
256    // 2) scroll [num-units] unit   (num-units is always either -1 or 1)
257    // 3) scroll [num-pages] page   (num-pages is always either -1 or 1)
258
259    if (!theAbstractions->existsCurrent())
260       return TCL_OK;
261
262    float newFirst;
263    bool anyChanges = processScrollCallback(interp, argc, argv,
264                            theAbstractions->getVertSBName(),
265                            theAbstractions->getVertSBOffset(),  // <= 0
266                            theAbstractions->getTotalVertPixUsed(),
267                            theAbstractions->getVisibleVertPix(),
268                            newFirst);
269
270    if (anyChanges)
271       anyChanges = theAbstractions->adjustVertSBOffset(newFirst);
272    
273    if (anyChanges)
274       initiateWhereAxisRedraw(interp, true);
275
276    return TCL_OK;
277 }
278
279 int whereAxisNewHorizScrollPositionCommand(ClientData, Tcl_Interp *interp,
280                                            int argc, char **argv) {
281    assert(haveSeenFirstGoodWhereAxisWid);
282
283    // The arguments will be one of:
284    // 1) moveto [fraction]
285    // 2) scroll [num-units] unit   (num-units is always either -1 or 1)
286    // 3) scroll [num-pages] page   (num-pages is always either -1 or 1)
287
288    if (!theAbstractions->existsCurrent())
289       return TCL_OK;
290
291    float newFirst;
292    bool anyChanges = processScrollCallback(interp, argc, argv,
293                            theAbstractions->getHorizSBName(),
294                            theAbstractions->getHorizSBOffset(), // <= 0
295                            theAbstractions->getTotalHorizPixUsed(),
296                            theAbstractions->getVisibleHorizPix(),
297                            newFirst);
298    if (anyChanges)
299       anyChanges = theAbstractions->adjustHorizSBOffset(newFirst);
300
301    if (anyChanges)
302       initiateWhereAxisRedraw(interp, true);   
303
304    return TCL_OK;
305 }
306
307 int whereAxisClearSelectionsCommand(ClientData, Tcl_Interp *interp,
308                                     int argc, char **) {
309    assert(haveSeenFirstGoodWhereAxisWid);
310
311    assert(argc == 1);
312    if (theAbstractions->existsCurrent()) {
313       theAbstractions->clearSelections(); // doesn't redraw
314       initiateWhereAxisRedraw(interp, true);
315    }
316  
317    return TCL_OK;
318 }
319
320 int whereAxisNavigateToCommand(ClientData, Tcl_Interp *interp,
321                                int argc, char **argv) {
322    assert(haveSeenFirstGoodWhereAxisWid);
323
324    assert(argc == 2);
325    const int level = atoi(argv[1]);
326
327    if (theAbstractions->existsCurrent()) {   
328       theAbstractions->navigateTo(level);
329
330       initiateWhereAxisRedraw(interp, true);
331    }
332
333    return TCL_OK;
334 }
335
336 int whereAxisChangeAbstractionCommand(ClientData, Tcl_Interp *interp,
337                                       int argc, char **argv) {
338    assert(haveSeenFirstGoodWhereAxisWid);
339
340    assert(argc==2);
341    const int absId = atoi(argv[1]); // base-1, not 0
342
343    if (theAbstractions->existsCurrent()) {
344       (void)theAbstractions->change(absId - 1);
345    
346       // We must assume that the toplevel window has been resized since
347       // the newly-displayed-whereAxis was set aside.  In short, we need to
348       // simulate a resize right now.
349       theAbstractions->resizeCurrent();
350
351       initiateWhereAxisRedraw(interp, true);   
352    }
353
354    return TCL_OK;
355 }
356
357 int whereAxisFindCommand(ClientData, Tcl_Interp *interp,
358                          int argc, char **argv) {
359    assert(haveSeenFirstGoodWhereAxisWid);
360
361    assert(argc == 2);
362    const char *str = argv[1];
363
364    if (theAbstractions->existsCurrent()) {
365       const int result = theAbstractions->find(str);
366          // 0 --> not found
367          // 1 --> found, and nothing had to be expanded (i.e. just a pure scroll)
368          // 2 --> found, and stuff had to be expanded (i.e. must redraw everything)
369    
370       if (result==1 || result==2)
371          initiateWhereAxisRedraw(interp, true);
372    }
373
374    return TCL_OK;
375 }
376
377 int altAnchorX, altAnchorY;
378 bool currentlyInstalledAltMoveHandler = false;
379 bool ignoreNextAltMove = false;
380
381 int whereAxisAltPressCommand(ClientData, Tcl_Interp *interp,
382                              int argc, char **argv) {
383    if (!haveSeenFirstGoodWhereAxisWid)
384       return TCL_OK;
385    if (!theAbstractions->existsCurrent())
386       return TCL_OK;
387
388    assert(argc==3);
389    int x = atoi(argv[1]);
390    int y = atoi(argv[2]);
391
392
393    if (currentlyInstalledAltMoveHandler) {
394       if (ignoreNextAltMove) {
395          ignoreNextAltMove = false;
396          return TCL_OK;
397       }
398
399       int deltax = x - altAnchorX;
400       int deltay = y - altAnchorY;
401 //      cout << "Scroll (" << deltax << "," << deltay << ")" << endl;
402
403       // add some extra speedup juice as an incentive to use alt-mousemove scrolling
404       deltax *= 4;
405       deltay *= 4;
406
407       theAbstractions->adjustHorizSBOffsetFromDeltaPix(deltax);
408       theAbstractions->adjustVertSBOffsetFromDeltaPix(deltay);
409
410       initiateWhereAxisRedraw(interp, true);
411
412       Tk_Window theTkWindow = theAbstractions->getTkWindow();
413
414 #if !defined(i386_unknown_nt4_0)
415       XWarpPointer(Tk_Display(theTkWindow),
416                    Tk_WindowId(theTkWindow),
417                    Tk_WindowId(theTkWindow),
418                    0, 0, 0, 0,
419                    altAnchorX, altAnchorY);
420 #else // !defined(i386_unknown_nt4_0)
421                 // TODO - implement warping behavior
422 #endif // !defined(i386_unknown_nt4_0)
423
424       ignoreNextAltMove = true;
425
426       return TCL_OK;
427    }
428    else {
429 //      cout << "I detect mouse-motion w/alt pressed at (" << x << ", " << y << ")" << "; installing handler" << endl;
430
431       altAnchorX = x;
432       altAnchorY = y;
433
434       currentlyInstalledAltMoveHandler = true;
435    }
436
437    return TCL_OK;
438 }
439
440 int whereAxisAltReleaseCommand(ClientData, Tcl_Interp *,
441                                int argc, char **) {
442 //   cout << "welcome to whereAxisAltReleaseCommand" << endl;
443
444    if (!haveSeenFirstGoodWhereAxisWid)
445       return TCL_OK;
446    if (!theAbstractions->existsCurrent())
447       return TCL_OK;
448
449    assert(argc==1);
450    
451    // Now un-install the mouse-move event handler that may have been
452    // installed by the above routine.
453
454    if (currentlyInstalledAltMoveHandler) {
455 //      cout << "releasing alt-move event handler now." << endl;
456       currentlyInstalledAltMoveHandler = false;
457    }
458    else {
459       // cout << "no need to release alt-move event handler (not installed?)" << endl;
460    }
461
462    return TCL_OK;
463 }
464
465
466 int
467 whereAxisDestroyHandler(ClientData, Tcl_Interp*, int, char **)
468 {
469
470    if (!haveSeenFirstGoodWhereAxisWid)
471       return TCL_OK;
472
473         // cleanup data owned by the whereAxis window
474    delete theAbstractions;
475    theAbstractions = NULL;
476
477    return TCL_OK;
478 }
479
480
481 /* ******************************************************************** */
482
483 #ifdef PARADYN
484 void whereAxisDrawTipsCallback(bool newValue) {
485    extern Tcl_Interp *interp;
486    if (newValue)
487       myTclEval(interp, "whereAxisDrawTips");
488    else
489       myTclEval(interp, "whereAxisEraseTips");
490 }
491 #endif
492
493 /* ******************************************************************** */
494
495 void deleteDummyProc(ClientData) {}
496 void installWhereAxisCommands(Tcl_Interp *interp) {
497    Tcl_CreateCommand(interp, "whereAxisConfigureHook", whereAxisResizeCallbackCommand,
498                      NULL, // clientData
499                      deleteDummyProc);
500    Tcl_CreateCommand(interp, "whereAxisExposeHook", whereAxisExposeCallbackCommand,
501                      NULL, deleteDummyProc);
502    Tcl_CreateCommand(interp, "whereAxisVisibilityHook",
503                      whereAxisVisibilityCallbackCommand,
504                      NULL, deleteDummyProc);
505    Tcl_CreateCommand(interp, "whereAxisSingleClickHook",
506                      whereAxisSingleClickCallbackCommand,
507                      NULL, deleteDummyProc);
508    Tcl_CreateCommand(interp, "whereAxisDoubleClickHook",
509                      whereAxisDoubleClickCallbackCommand,
510                      NULL, deleteDummyProc);
511    Tcl_CreateCommand(interp, "whereAxisShiftDoubleClickHook",
512                      whereAxisShiftDoubleClickCallbackCommand,
513                      NULL, deleteDummyProc);
514    Tcl_CreateCommand(interp, "whereAxisCtrlDoubleClickHook",
515                      whereAxisCtrlDoubleClickCallbackCommand,
516                      NULL, deleteDummyProc);
517    Tcl_CreateCommand(interp, "whereAxisNewVertScrollPosition",
518                      whereAxisNewVertScrollPositionCommand,
519                      NULL, deleteDummyProc);
520    Tcl_CreateCommand(interp, "whereAxisNewHorizScrollPosition",
521                      whereAxisNewHorizScrollPositionCommand,
522                      NULL, deleteDummyProc);
523    Tcl_CreateCommand(interp, "whereAxisClearSelections",
524                      whereAxisClearSelectionsCommand,
525                      NULL, deleteDummyProc);
526    Tcl_CreateCommand(interp, "whereAxisNavigateTo", whereAxisNavigateToCommand,
527                      NULL, deleteDummyProc);
528    Tcl_CreateCommand(interp, "whereAxisChangeAbstraction",
529                      whereAxisChangeAbstractionCommand,
530                      NULL, deleteDummyProc);
531    Tcl_CreateCommand(interp, "whereAxisFindHook", whereAxisFindCommand,
532                      NULL, deleteDummyProc);
533    Tcl_CreateCommand(interp, "whereAxisAltPressHook", whereAxisAltPressCommand,
534                      NULL, deleteDummyProc);
535    Tcl_CreateCommand(interp, "whereAxisAltReleaseHook", whereAxisAltReleaseCommand,
536                      NULL, deleteDummyProc);
537    Tcl_CreateCommand(interp, "whereAxisDestroyHook", whereAxisDestroyHandler,
538                      NULL, deleteDummyProc);
539 }
540
541 void unInstallWhereAxisCommands(Tcl_Interp *interp) {
542    Tcl_DeleteCommand(interp, "whereAxisAltReleaseHook");
543    Tcl_DeleteCommand(interp, "whereAxisAltPressHook");
544    Tcl_DeleteCommand(interp, "whereAxisFindHook");
545    Tcl_DeleteCommand(interp, "whereAxisChangeAbstraction");
546    Tcl_DeleteCommand(interp, "whereAxisNavigateTo");
547    Tcl_DeleteCommand(interp, "whereAxisClearSelections");
548    Tcl_DeleteCommand(interp, "whereAxisNewHorizScrollPosition");
549    Tcl_DeleteCommand(interp, "whereAxisNewVertScrollPosition");
550    Tcl_DeleteCommand(interp, "whereAxisCtrlDoubleClickHook");
551    Tcl_DeleteCommand(interp, "whereAxisShiftDoubleClickHook");
552    Tcl_DeleteCommand(interp, "whereAxisDoubleClickHook");
553    Tcl_DeleteCommand(interp, "whereAxisSingleClickHook");
554    Tcl_DeleteCommand(interp, "whereAxisExposeHook");
555    Tcl_DeleteCommand(interp, "whereAxisConfigureHook");
556    Tcl_DeleteCommand(interp, "whereAxisDestroyHook");
557 }