Changed to eliminate inline cvs logs -> cvs $Id$
[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 /* $Id: whereAxisTcl.C,v 1.14 1999/04/27 16:03:56 nash Exp $ */
48
49 #ifndef PARADYN
50 // The test program has "correct" -I paths already set
51 #include "DMinclude.h" // for resourceHandle
52 #else
53 #include "paradyn/src/DMthread/DMinclude.h" // for resourceHandle
54 #endif
55
56 #include "abstractions.h"
57 #include "whereAxisTcl.h"
58 #include "tkTools.h"
59
60 // Here is the main where axis global variable:
61 abstractions *theAbstractions;
62
63 extern bool haveSeenFirstGoodWhereAxisWid; // test.C
64 extern bool tryFirstGoodWhereAxisWid(Tcl_Interp *, Tk_Window); // test.C
65
66 void whereAxisWhenIdleDrawRoutine(ClientData cd) {
67    assert(haveSeenFirstGoodWhereAxisWid);
68
69    const bool doubleBuffer = (bool)cd;
70
71 #ifdef PARADYN
72    const bool isXsynchOn = false;
73 #else
74    extern bool xsynchronize;
75    const bool isXsynchOn = xsynchronize;
76 #endif
77
78    theAbstractions->drawCurrent(doubleBuffer, isXsynchOn);
79 }
80 tkInstallIdle whereAxisDrawWhenIdle(&whereAxisWhenIdleDrawRoutine);
81
82 void initiateWhereAxisRedraw(Tcl_Interp *, bool doubleBuffer) {
83    whereAxisDrawWhenIdle.install((ClientData)doubleBuffer);
84 }
85
86 int whereAxisResizeCallbackCommand(ClientData, Tcl_Interp *interp,
87                                    int, char **) {
88    if (!tryFirstGoodWhereAxisWid(interp, Tk_MainWindow(interp)))
89       return TCL_ERROR;
90
91    if (theAbstractions->existsCurrent()) {
92       theAbstractions->resizeCurrent();
93       initiateWhereAxisRedraw(interp, true); // true-->use double-buffering
94    }
95
96    return TCL_OK;
97 }
98
99 int whereAxisExposeCallbackCommand(ClientData, Tcl_Interp *interp,
100                                    int argc, char **argv) {
101    if (!tryFirstGoodWhereAxisWid(interp, Tk_MainWindow(interp)))
102       return TCL_ERROR;
103
104    assert(argc == 2);
105
106    const int count = atoi(argv[1]); // Xevent count field (we should only redraw if 0)
107
108    if (theAbstractions->existsCurrent() && count==0)
109       initiateWhereAxisRedraw(interp, true); // true --> double buffer
110
111    return TCL_OK;
112 }
113
114 int whereAxisVisibilityCallbackCommand(ClientData, Tcl_Interp *interp,
115                                        int argc, char **argv) {
116    if (!tryFirstGoodWhereAxisWid(interp, Tk_MainWindow(interp)))
117       return TCL_ERROR;
118
119    assert(argc == 2);
120
121    char *newVisibility = argv[1];
122
123    if (0==strcmp(newVisibility, "VisibilityUnobscured"))
124       theAbstractions->makeVisibilityUnobscured();
125    else if (0==strcmp(newVisibility, "VisibilityPartiallyObscured"))
126       theAbstractions->makeVisibilityPartiallyObscured();
127    else if (0==strcmp(newVisibility, "VisibilityFullyObscured"))
128       theAbstractions->makeVisibilityFullyObscured();
129    else {
130       cerr << "unrecognized visibility " << newVisibility << endl;
131       return TCL_ERROR;
132    }
133
134    return TCL_OK;
135 }
136
137 int whereAxisSingleClickCallbackCommand(ClientData, Tcl_Interp *,
138                                         int argc, char **argv) {
139    assert(haveSeenFirstGoodWhereAxisWid);
140
141    assert(argc == 3);
142    const int x = atoi(argv[1]);
143    const int y = atoi(argv[2]);
144
145    if (theAbstractions->existsCurrent())
146       theAbstractions->processSingleClick(x, y);
147
148    return TCL_OK;
149 }
150
151 int whereAxisDoubleClickCallbackCommand(ClientData, Tcl_Interp *interp,
152                                         int argc, char **argv) {
153    assert(haveSeenFirstGoodWhereAxisWid);
154    assert(argc==3);
155
156    const int x = atoi(argv[1]);
157    const int y = atoi(argv[2]);
158
159    if (theAbstractions->existsCurrent()) {
160       bool needToRedrawAll=theAbstractions->processDoubleClick(x, y);
161       if (needToRedrawAll)
162          initiateWhereAxisRedraw(interp, true); // true--> use double buffer
163    }
164
165    return TCL_OK;
166 }
167
168 int whereAxisShiftDoubleClickCallbackCommand(ClientData, Tcl_Interp *interp,
169                                              int argc, char **argv) {
170    assert(haveSeenFirstGoodWhereAxisWid);
171    assert(argc == 3);
172
173    const int x = atoi(argv[1]);
174    const int y = atoi(argv[2]);
175
176    if (theAbstractions->existsCurrent()) {
177       bool needToRedrawAll=theAbstractions->processShiftDoubleClick(x, y);
178  
179       if (needToRedrawAll)
180          initiateWhereAxisRedraw(interp, true);
181    }
182
183    return TCL_OK;
184 }
185
186 int whereAxisCtrlDoubleClickCallbackCommand(ClientData, Tcl_Interp *interp,
187                                             int argc, char **argv) {
188    assert(haveSeenFirstGoodWhereAxisWid);
189
190    assert(argc==3);
191    const int x = atoi(argv[1]);
192    const int y = atoi(argv[2]);
193
194    if (theAbstractions->existsCurrent()) {
195       bool needToRedrawAll=theAbstractions->processCtrlDoubleClick(x, y);
196  
197       if (needToRedrawAll)
198          initiateWhereAxisRedraw(interp, true);
199    }
200
201    return TCL_OK;
202 }
203
204 int whereAxisNewVertScrollPositionCommand(ClientData, Tcl_Interp *interp,
205                                           int argc, char **argv) {
206    assert(haveSeenFirstGoodWhereAxisWid);
207
208    // The arguments will be one of:
209    // 1) moveto [fraction]
210    // 2) scroll [num-units] unit   (num-units is always either -1 or 1)
211    // 3) scroll [num-pages] page   (num-pages is always either -1 or 1)
212
213    if (!theAbstractions->existsCurrent())
214       return TCL_OK;
215
216    float newFirst;
217    bool anyChanges = processScrollCallback(interp, argc, argv,
218                            theAbstractions->getVertSBName(),
219                            theAbstractions->getVertSBOffset(),  // <= 0
220                            theAbstractions->getTotalVertPixUsed(),
221                            theAbstractions->getVisibleVertPix(),
222                            newFirst);
223
224    if (anyChanges)
225       anyChanges = theAbstractions->adjustVertSBOffset(newFirst);
226    
227    if (anyChanges)
228       initiateWhereAxisRedraw(interp, true);
229
230    return TCL_OK;
231 }
232
233 int whereAxisNewHorizScrollPositionCommand(ClientData, Tcl_Interp *interp,
234                                            int argc, char **argv) {
235    assert(haveSeenFirstGoodWhereAxisWid);
236
237    // The arguments will be one of:
238    // 1) moveto [fraction]
239    // 2) scroll [num-units] unit   (num-units is always either -1 or 1)
240    // 3) scroll [num-pages] page   (num-pages is always either -1 or 1)
241
242    if (!theAbstractions->existsCurrent())
243       return TCL_OK;
244
245    float newFirst;
246    bool anyChanges = processScrollCallback(interp, argc, argv,
247                            theAbstractions->getHorizSBName(),
248                            theAbstractions->getHorizSBOffset(), // <= 0
249                            theAbstractions->getTotalHorizPixUsed(),
250                            theAbstractions->getVisibleHorizPix(),
251                            newFirst);
252    if (anyChanges)
253       anyChanges = theAbstractions->adjustHorizSBOffset(newFirst);
254
255    if (anyChanges)
256       initiateWhereAxisRedraw(interp, true);   
257
258    return TCL_OK;
259 }
260
261 int whereAxisClearSelectionsCommand(ClientData, Tcl_Interp *interp,
262                                     int argc, char **) {
263    assert(haveSeenFirstGoodWhereAxisWid);
264
265    assert(argc == 1);
266    if (theAbstractions->existsCurrent()) {
267       theAbstractions->clearSelections(); // doesn't redraw
268       initiateWhereAxisRedraw(interp, true);
269    }
270  
271    return TCL_OK;
272 }
273
274 int whereAxisNavigateToCommand(ClientData, Tcl_Interp *interp,
275                                int argc, char **argv) {
276    assert(haveSeenFirstGoodWhereAxisWid);
277
278    assert(argc == 2);
279    const int level = atoi(argv[1]);
280
281    if (theAbstractions->existsCurrent()) {   
282       theAbstractions->navigateTo(level);
283
284       initiateWhereAxisRedraw(interp, true);
285    }
286
287    return TCL_OK;
288 }
289
290 int whereAxisChangeAbstractionCommand(ClientData, Tcl_Interp *interp,
291                                       int argc, char **argv) {
292    assert(haveSeenFirstGoodWhereAxisWid);
293
294    assert(argc==2);
295    const int absId = atoi(argv[1]); // base-1, not 0
296
297    if (theAbstractions->existsCurrent()) {
298       (void)theAbstractions->change(absId - 1);
299    
300       // We must assume that the toplevel window has been resized since
301       // the newly-displayed-whereAxis was set aside.  In short, we need to
302       // simulate a resize right now.
303       theAbstractions->resizeCurrent();
304
305       initiateWhereAxisRedraw(interp, true);   
306    }
307
308    return TCL_OK;
309 }
310
311 int whereAxisFindCommand(ClientData, Tcl_Interp *interp,
312                          int argc, char **argv) {
313    assert(haveSeenFirstGoodWhereAxisWid);
314
315    assert(argc == 2);
316    const char *str = argv[1];
317
318    if (theAbstractions->existsCurrent()) {
319       const int result = theAbstractions->find(str);
320          // 0 --> not found
321          // 1 --> found, and nothing had to be expanded (i.e. just a pure scroll)
322          // 2 --> found, and stuff had to be expanded (i.e. must redraw everything)
323    
324       if (result==1 || result==2)
325          initiateWhereAxisRedraw(interp, true);
326    }
327
328    return TCL_OK;
329 }
330
331 int altAnchorX, altAnchorY;
332 bool currentlyInstalledAltMoveHandler = false;
333 bool ignoreNextAltMove = false;
334
335 int whereAxisAltPressCommand(ClientData, Tcl_Interp *interp,
336                              int argc, char **argv) {
337    if (!haveSeenFirstGoodWhereAxisWid)
338       return TCL_OK;
339    if (!theAbstractions->existsCurrent())
340       return TCL_OK;
341
342    assert(argc==3);
343    int x = atoi(argv[1]);
344    int y = atoi(argv[2]);
345
346
347    if (currentlyInstalledAltMoveHandler) {
348       if (ignoreNextAltMove) {
349          ignoreNextAltMove = false;
350          return TCL_OK;
351       }
352
353       int deltax = x - altAnchorX;
354       int deltay = y - altAnchorY;
355 //      cout << "Scroll (" << deltax << "," << deltay << ")" << endl;
356
357       // add some extra speedup juice as an incentive to use alt-mousemove scrolling
358       deltax *= 4;
359       deltay *= 4;
360
361       theAbstractions->adjustHorizSBOffsetFromDeltaPix(deltax);
362       theAbstractions->adjustVertSBOffsetFromDeltaPix(deltay);
363
364       initiateWhereAxisRedraw(interp, true);
365
366       Tk_Window theTkWindow = theAbstractions->getTkWindow();
367
368 #if !defined(i386_unknown_nt4_0)
369       XWarpPointer(Tk_Display(theTkWindow),
370                    Tk_WindowId(theTkWindow),
371                    Tk_WindowId(theTkWindow),
372                    0, 0, 0, 0,
373                    altAnchorX, altAnchorY);
374 #else // !defined(i386_unknown_nt4_0)
375                 // TODO - implement warping behavior
376 #endif // !defined(i386_unknown_nt4_0)
377
378       ignoreNextAltMove = true;
379
380       return TCL_OK;
381    }
382    else {
383 //      cout << "I detect mouse-motion w/alt pressed at (" << x << ", " << y << ")" << "; installing handler" << endl;
384
385       altAnchorX = x;
386       altAnchorY = y;
387
388       currentlyInstalledAltMoveHandler = true;
389    }
390
391    return TCL_OK;
392 }
393
394 int whereAxisAltReleaseCommand(ClientData, Tcl_Interp *,
395                                int argc, char **) {
396 //   cout << "welcome to whereAxisAltReleaseCommand" << endl;
397
398    if (!haveSeenFirstGoodWhereAxisWid)
399       return TCL_OK;
400    if (!theAbstractions->existsCurrent())
401       return TCL_OK;
402
403    assert(argc==1);
404    
405    // Now un-install the mouse-move event handler that may have been
406    // installed by the above routine.
407
408    if (currentlyInstalledAltMoveHandler) {
409 //      cout << "releasing alt-move event handler now." << endl;
410       currentlyInstalledAltMoveHandler = false;
411    }
412    else {
413       // cout << "no need to release alt-move event handler (not installed?)" << endl;
414    }
415
416    return TCL_OK;
417 }
418
419
420 int
421 whereAxisDestroyHandler(ClientData, Tcl_Interp*, int, char **)
422 {
423
424    if (!haveSeenFirstGoodWhereAxisWid)
425       return TCL_OK;
426
427         // cleanup data owned by the whereAxis window
428    delete theAbstractions;
429    theAbstractions = NULL;
430
431    return TCL_OK;
432 }
433
434
435 /* ******************************************************************** */
436
437 #ifdef PARADYN
438 void whereAxisDrawTipsCallback(bool newValue) {
439    extern Tcl_Interp *interp;
440    if (newValue)
441       myTclEval(interp, "whereAxisDrawTips");
442    else
443       myTclEval(interp, "whereAxisEraseTips");
444 }
445 #endif
446
447 /* ******************************************************************** */
448
449 void deleteDummyProc(ClientData) {}
450 void installWhereAxisCommands(Tcl_Interp *interp) {
451    Tcl_CreateCommand(interp, "whereAxisConfigureHook", whereAxisResizeCallbackCommand,
452                      NULL, // clientData
453                      deleteDummyProc);
454    Tcl_CreateCommand(interp, "whereAxisExposeHook", whereAxisExposeCallbackCommand,
455                      NULL, deleteDummyProc);
456    Tcl_CreateCommand(interp, "whereAxisVisibilityHook",
457                      whereAxisVisibilityCallbackCommand,
458                      NULL, deleteDummyProc);
459    Tcl_CreateCommand(interp, "whereAxisSingleClickHook",
460                      whereAxisSingleClickCallbackCommand,
461                      NULL, deleteDummyProc);
462    Tcl_CreateCommand(interp, "whereAxisDoubleClickHook",
463                      whereAxisDoubleClickCallbackCommand,
464                      NULL, deleteDummyProc);
465    Tcl_CreateCommand(interp, "whereAxisShiftDoubleClickHook",
466                      whereAxisShiftDoubleClickCallbackCommand,
467                      NULL, deleteDummyProc);
468    Tcl_CreateCommand(interp, "whereAxisCtrlDoubleClickHook",
469                      whereAxisCtrlDoubleClickCallbackCommand,
470                      NULL, deleteDummyProc);
471    Tcl_CreateCommand(interp, "whereAxisNewVertScrollPosition",
472                      whereAxisNewVertScrollPositionCommand,
473                      NULL, deleteDummyProc);
474    Tcl_CreateCommand(interp, "whereAxisNewHorizScrollPosition",
475                      whereAxisNewHorizScrollPositionCommand,
476                      NULL, deleteDummyProc);
477    Tcl_CreateCommand(interp, "whereAxisClearSelections",
478                      whereAxisClearSelectionsCommand,
479                      NULL, deleteDummyProc);
480    Tcl_CreateCommand(interp, "whereAxisNavigateTo", whereAxisNavigateToCommand,
481                      NULL, deleteDummyProc);
482    Tcl_CreateCommand(interp, "whereAxisChangeAbstraction",
483                      whereAxisChangeAbstractionCommand,
484                      NULL, deleteDummyProc);
485    Tcl_CreateCommand(interp, "whereAxisFindHook", whereAxisFindCommand,
486                      NULL, deleteDummyProc);
487    Tcl_CreateCommand(interp, "whereAxisAltPressHook", whereAxisAltPressCommand,
488                      NULL, deleteDummyProc);
489    Tcl_CreateCommand(interp, "whereAxisAltReleaseHook", whereAxisAltReleaseCommand,
490                      NULL, deleteDummyProc);
491    Tcl_CreateCommand(interp, "whereAxisDestroyHook", whereAxisDestroyHandler,
492                      NULL, deleteDummyProc);
493 }
494
495 void unInstallWhereAxisCommands(Tcl_Interp *interp) {
496    Tcl_DeleteCommand(interp, "whereAxisAltReleaseHook");
497    Tcl_DeleteCommand(interp, "whereAxisAltPressHook");
498    Tcl_DeleteCommand(interp, "whereAxisFindHook");
499    Tcl_DeleteCommand(interp, "whereAxisChangeAbstraction");
500    Tcl_DeleteCommand(interp, "whereAxisNavigateTo");
501    Tcl_DeleteCommand(interp, "whereAxisClearSelections");
502    Tcl_DeleteCommand(interp, "whereAxisNewHorizScrollPosition");
503    Tcl_DeleteCommand(interp, "whereAxisNewVertScrollPosition");
504    Tcl_DeleteCommand(interp, "whereAxisCtrlDoubleClickHook");
505    Tcl_DeleteCommand(interp, "whereAxisShiftDoubleClickHook");
506    Tcl_DeleteCommand(interp, "whereAxisDoubleClickHook");
507    Tcl_DeleteCommand(interp, "whereAxisSingleClickHook");
508    Tcl_DeleteCommand(interp, "whereAxisExposeHook");
509    Tcl_DeleteCommand(interp, "whereAxisConfigureHook");
510    Tcl_DeleteCommand(interp, "whereAxisDestroyHook");
511 }