dictionary_lite --> dictionary_hash
[dyninst.git] / paradyn / src / UIthread / pdLogo.C
1 /*
2  * Copyright (c) 1996 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 // pdLogo.C
43
44 /*
45  * $Log: pdLogo.C,v $
46  * Revision 1.3  1997/10/28 20:35:56  tamches
47  * dictionary_lite --> dictionary_hash
48  *
49  * Revision 1.2  1996/08/16 21:07:01  tamches
50  * updated copyright for release 1.1
51  *
52  * Revision 1.1  1995/11/29 00:19:46  tamches
53  * first version of pdLogo
54  *
55  */
56
57 #include "pdLogo.h"
58
59 dictionary_hash<string, pdLogo::logoStruct> pdLogo::all_installed_logos(string::hash,
60                                                                        9);
61 dictionary_hash<string, pdLogo *> pdLogo::all_logos(string::hash, 9);
62
63 bool pdLogo::tryFirst() {
64    if (theLogo != None)
65       return true;
66
67    if (Tk_WindowId(theTkWindow) == 0)
68       return false; // not yet ready
69
70    theLogo = XCreatePixmapFromBitmapData(Tk_Display(theTkWindow),
71                                          Tk_WindowId(theTkWindow),
72                                          (char *)theLogoData.rawData,
73                                          theLogoData.width, theLogoData.height,
74                                          foregroundColor->pixel,
75                                          backgroundColor->pixel,
76                                          Tk_Depth(theTkWindow)
77                                          );
78    assert(theLogo);
79
80    XGCValues values;
81    copyGC = Tk_GetGC(theTkWindow,
82                      0, // (!)
83                      &values);
84
85    return true;
86 }
87
88 void pdLogo::draw() {
89    if (!tryFirst())
90       return;
91
92    installer.install(this); // calls real_draw() when idle
93 }
94
95 void pdLogo::real_draw(ClientData cd) {
96    pdLogo *pthis = (pdLogo *)cd;
97    assert(pthis);
98
99    XCopyArea(Tk_Display(pthis->theTkWindow),
100              pthis->theLogo, // src drawable
101              Tk_WindowId(pthis->theTkWindow), // dest drawable
102              pthis->copyGC,
103              0, 0, // src x, y
104              pthis->theLogoData.width, pthis->theLogoData.height,
105              pthis->borderPix, pthis->borderPix // dest x, y
106              );
107 }
108
109 /* ********************************************************** */
110
111 pdLogo::pdLogo(Tcl_Interp *iInterp, Tk_Window iTkWindow,
112                void *iRawData, unsigned iWidth, unsigned iHeight) :
113                     installer(&pdLogo::real_draw) {
114    theLogoData.rawData = iRawData;
115    theLogoData.width = iWidth;
116    theLogoData.height = iHeight;
117    
118    interp = iInterp;
119    theTkWindow = iTkWindow;
120    theTkWindowName = string(Tk_PathName(theTkWindow));
121    theDisplay = Tk_Display(theTkWindow);
122
123    myTclEval(interp, theTkWindowName + " cget -borderwidth");
124    borderPix = atoi(interp->result);
125
126    myTclEval(interp, theTkWindowName + " cget -highlightcolor");
127    const string foregroundColorName = string(interp->result);
128
129    myTclEval(interp, theTkWindowName + " cget -background");
130    const string backgroundColorName = string(interp->result);
131
132    theLogo = None;
133
134    foregroundColor = Tk_GetColor(interp, theTkWindow,
135                                  Tk_GetUid(foregroundColorName.string_of()));
136    assert(foregroundColor);
137
138    backgroundColor = Tk_GetColor(interp, theTkWindow,
139                                  Tk_GetUid(backgroundColorName.string_of()));
140    assert(backgroundColor);
141
142    copyGC = None;
143 }
144
145 pdLogo::~pdLogo() {
146    if (copyGC)
147       Tk_FreeGC(theDisplay, copyGC);
148
149    if (theLogo)
150       XFreePixmap(theDisplay, theLogo);
151
152    Tk_FreeColor(foregroundColor);
153    Tk_FreeColor(backgroundColor);
154 }
155
156 /* ******************************************************************* */
157
158 int pdLogo::install_fixed_logo(const string &str,
159                                void *rawData, unsigned width, unsigned height) {
160    // we have no uninstall_fixed_logo since there's not big need for it.
161    if (all_installed_logos.defines(str)) {
162       cout << "install_fixed_logo (" << str << "): already installed! (ignoring)" << endl;
163       return TCL_OK;
164    }
165    logoStruct l;
166    l.rawData = rawData;
167    l.width = width;
168    l.height = height;;
169    all_installed_logos[str] = l;
170
171    return TCL_OK;
172 }
173
174 int pdLogo::makeLogoCommand(ClientData cd, Tcl_Interp *interp,
175                             int argc, char **argv) {
176    // args: [0] (implicit) the command name
177    // 1) tk window name   2) logo name (previously installed via install_fixed_logo)
178    // 3) relief           4) border pix       5) color
179    // NOTE: ClientData must point to a Tk_Window created by Tk_CreateMainWindow()
180    if (argc != 6) {
181       cerr << argv[0] << " requires 5 args (found " << argc-1 << ")" << endl;
182       exit(5);
183    }
184    
185    assert(argc == 6);
186    const string theTkWindowName = argv[1];
187    const string theLogoName     = argv[2];
188    const string reliefString    = argv[3];
189    unsigned borderPix           = atoi(argv[4]);
190    const string colorString     = argv[5];
191
192    if (!all_installed_logos.defines(theLogoName)) {
193       cout << argv[0] << ": sorry, the logo " << theLogoName << " hasn't been installed" << endl;
194       exit(5);
195    }
196    if (all_logos.defines(theTkWindowName)) {
197       cout << argv[0] << " -- sorry, the tk window name " << theTkWindowName << " is already in the dictionary (didn't flush on window close?)" << endl;
198       exit(5);
199    }
200
201    Tk_Window rootTkWindow = (Tk_Window)cd;
202
203    // Obtain the logo from the installed-logos dictionary:
204    assert(all_installed_logos.defines(theLogoName));
205    logoStruct &l = all_installed_logos[theLogoName];
206
207    // create a frame widget:
208    myTclEval(interp, string("frame ") + theTkWindowName +
209              " -width " + string(l.width + 2*borderPix) +
210              " -height " + string(l.height + 2*borderPix) +
211              " -relief " + reliefString +
212              " -borderwidth " + string(borderPix) +
213              " -highlightcolor " + colorString);
214
215    // At last, we can obtain the Tk_Window
216    Tk_Window theTkWindow = Tk_NameToWindow(interp, theTkWindowName.string_of(),
217                                            rootTkWindow);
218    if (theTkWindow == NULL) {
219       cout << "pdLogo::createCommand() -- sorry, window " << theTkWindowName <<
220               " does not exist (could not create properly?)" << endl;
221       exit(5);
222    }
223
224    pdLogo *theLogo = new pdLogo(interp, theTkWindow,
225                                 l.rawData, l.width, l.height);
226       // constructor does nothing terribly interesting
227    assert(theLogo);
228
229    all_logos[theTkWindowName] = theLogo;
230
231    // now create the bindings.  We call the tk "bind" command.  This requires
232    // us to do 2 Tcl_CreateCommand()'s.  We do this here if the commands
233    // don't already exist.
234    // the commands are: "pdLogoDrawCommand" and "pdLogoDestroyCommand"
235    Tcl_CmdInfo dummy;
236    if (0==Tcl_GetCommandInfo(interp, "pdLogoDrawCommand", &dummy))
237       Tcl_CreateCommand(interp, "pdLogoDrawCommand", &pdLogo::drawCallback,
238                         NULL, NULL);
239    if (0==Tcl_GetCommandInfo(interp, "pdLogoDestroyCommand", &dummy))
240       Tcl_CreateCommand(interp, "pdLogoDestroyCommand", &pdLogo::destroyCallback,
241                         NULL, NULL);
242
243    const string bindStringPrefix = string("bind ") + theTkWindowName + " ";
244    myTclEval(interp, bindStringPrefix + "<Configure> {pdLogoDrawCommand %W}");
245    myTclEval(interp, bindStringPrefix + "<Expose> {pdLogoDrawCommand %W}");
246    myTclEval(interp, bindStringPrefix + "<Destroy> {pdLogoDestroyCommand %W}");
247    return TCL_OK;      
248 }
249
250 int pdLogo::drawCallback(ClientData, Tcl_Interp *,
251                          int argc, char **argv) {
252    assert(argc == 2);
253
254    const string theTkWindowName = argv[1];
255
256    assert(all_logos.defines(theTkWindowName));
257    pdLogo *pthis = all_logos[theTkWindowName];
258    assert(pthis);
259
260    pthis->draw();
261
262    return TCL_OK;
263 }
264
265 int pdLogo::destroyCallback(ClientData, Tcl_Interp *,
266                             int argc, char **argv) {
267    // makeLogoCommand rigs things s.t. this is called when the window enclosing
268    // the logo is destroyed.  sent 1 arg: the tk window name
269    assert(argc == 2);
270
271    const string theTkWindowName = argv[1];
272    
273    assert(all_logos.defines(theTkWindowName));
274
275    pdLogo *pthis = all_logos[theTkWindowName];
276    assert(pthis);
277    delete pthis; // destructor does nothing interesting
278
279    all_logos.undef(theTkWindowName); // can't use pthis->theTkWindowName, which
280       // has just been deallocated!
281
282    return TCL_OK;
283 }