1 /****************************************************************************
2     Copyright (C) 1987-2015 by Jeffery P. Hansen
3 
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License along
15     with this program; if not, write to the Free Software Foundation, Inc.,
16     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 
18     Last edit by hansen on Wed Dec 31 17:16:16 2008
19 ****************************************************************************/
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <ctype.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <assert.h>
26 #include "tkgate.h"
27 #include <X11/Xutil.h>
28 
29 /*
30  *  Module Symbol Handling
31  *
32  *  The main class for describing a module symbol is a GModSymbol.  The GModSymbol
33  *  object describes the locations of ports and contains the bitmap data for the
34  *  normal and bold symbols.  However, it does not directly contain the X11 Pixmap
35  *  or Icon objects.  The reason for this is that the standard undo/redo functions
36  *  can not be applied to Pixmaps.  The Pixmap and Icon objects are instead managed
37  *  by the MSS (Module Symbol Sever).  The MSS manages a set of MssSymbol objects,
38  *  each of which contains the Pixmap and Icon objects corresponding to a single
39  *  GModSymbol.  The MSS uses standard malloc/free memory management instead of the
40  *  ob_malloc/ob_free management used by the rest of tkgate.  Each entry in the
41  *  MSS is identified by an integer "gid" which is used by the GModSymbol object
42  *  to look up its corresponding MssSymbol object.  The MSS is managed as a cache
43  *  with only the last MSS_SIZE most recently used entries being kept.  If an antry
44  *  is not used for a long time, it will be flushed and the associated Pixmap
45  *  objects deleted.  This way, MssSymbol objects corresponding to GModSymbol
46  *  objects which have been deleted will eventually be reclaimed.
47  */
48 
49 #define DEBUG_MOD_SYM 0
50 
51 
52 #define MSS_SIZE	128		/* Hash table size for MSS */
53 #define MSS_MAXENTRIES	128		/* Maximum number of entries in MSS table */
54 
55 typedef struct mss_symbol MssSymbol;
56 
57 struct mss_symbol {
58   unsigned	me_gid;			/* Id of symbol data */
59   Pixmap	me_pixmap;		/* Pixmap data for this entry */
60   Icon		*me_normal[NUMORIENTS];	/* Normal icons for this entry */
61   Icon		*me_select[NUMORIENTS];	/* Bold icons for this entry */
62   MssSymbol	*me_next;		/* Next entry in hash chain */
63   MssSymbol	*me_luNext;		/* Next entry in last use chain */
64   MssSymbol	*me_luPrev;		/* Previous entry in last use chain */
65 };
66 
67 typedef struct {
68   unsigned	mss_idCount;		/* ID counter */
69   unsigned	mss_numEntries;		/* Current number of entries */
70   MssSymbol	*mss_ents[MSS_SIZE];	/* Table entries */
71   MssSymbol	*mss_mru;		/* Most recently used */
72   MssSymbol	*mss_lru;		/* Least recently used */
73 } MSS;
74 
75 /*
76  * Table of module sever symbols.
77  */
78 static MSS mss;
79 
80 /*
81  * Table of symbols
82  */
83 static PHash *symbolTable = 0;
84 
85 static int defaultSymbol_x = 5;
86 static int defaultSymbol_y = 5;
87 static char *defaultSymbol_data =
88 "#define defaultSymbol_width 29\n"
89 "#define defaultSymbol_height 29\n"
90 "static unsigned char defaultSymbol_bits[] = {\n"
91 "   0xff, 0xff, 0x07, 0x00, 0x01, 0x00, 0x18, 0x00, 0x01, 0x00, 0x60, 0x00,\n"
92 "   0x01, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02,\n"
93 "   0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x08,\n"
94 "   0x01, 0x00, 0x00, 0x08, 0x11, 0x39, 0x18, 0x10, 0x11, 0x49, 0x24, 0x10,\n"
95 "   0x11, 0x89, 0x04, 0x10, 0x11, 0x89, 0x18, 0x10, 0x11, 0x89, 0x20, 0x10,\n"
96 "   0x11, 0x49, 0x24, 0x10, 0xe1, 0x38, 0x18, 0x10, 0x01, 0x00, 0x00, 0x10,\n"
97 "   0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, 0x08,\n"
98 "   0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x02,\n"
99 "   0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x80, 0x00, 0x01, 0x00, 0x60, 0x00,\n"
100 "   0x01, 0x00, 0x18, 0x00, 0xff, 0xff, 0x07, 0x00};\n";
101 
102 
103 static char *defaultBoldSymbol_data =
104 "#define y_width 29\n"
105 "#define y_height 29\n"
106 "static unsigned char y_bits[] = {\n"
107 "   0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x1f, 0x00, 0x03, 0x00, 0x78, 0x00,\n"
108 "   0x03, 0x00, 0xe0, 0x00, 0x03, 0x00, 0x80, 0x01, 0x03, 0x00, 0x00, 0x03,\n"
109 "   0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x0c,\n"
110 "   0x03, 0x00, 0x00, 0x0c, 0x33, 0x7b, 0x38, 0x18, 0x33, 0xdb, 0x6c, 0x18,\n"
111 "   0x33, 0x9b, 0x0d, 0x18, 0x33, 0x9b, 0x39, 0x18, 0x33, 0x9b, 0x61, 0x18,\n"
112 "   0x33, 0xdb, 0x6c, 0x18, 0xe3, 0x79, 0x38, 0x18, 0x03, 0x00, 0x00, 0x18,\n"
113 "   0x03, 0x00, 0x00, 0x18, 0x03, 0x00, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x0c,\n"
114 "   0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x06, 0x03, 0x00, 0x00, 0x03,\n"
115 "   0x03, 0x00, 0x80, 0x01, 0x03, 0x00, 0xe0, 0x00, 0x03, 0x00, 0x78, 0x00,\n"
116 "   0xff, 0xff, 0x1f, 0x00, 0xff, 0xff, 0x07, 0x00};\n";
117 
118 /*
119  * Rotate (x,y) around the point (cx, cy)
120  */
rotatePoint(int * x,int * y,int cx,int cy,int r)121 static void rotatePoint(int *x,int *y,int cx,int cy,int r)
122 {
123   static int isin[] = {0,1,0,-1};
124   static int icos[] = {1,0,-1,0};
125   int nx = *x - cx;
126   int ny = -(*y - cy);
127 
128   *x = nx*icos[r] - ny*isin[r];
129   *y = -(nx*isin[r] + ny*icos[r]);
130 
131   *x += cx;
132   *y += cy;
133 }
134 
135 /*****************************************************************************
136  *
137  * Reverse the bits in a byte.
138  *
139  * Parameters:
140  *      x		Number in which to reverse bytes
141  *
142  * Returns:		Byte reversed value.
143  *
144  *****************************************************************************/
reverseBits(unsigned char x)145 static unsigned char reverseBits(unsigned char x)
146 {
147   static unsigned char revTab[] = {
148   //0  1  2   3  4  5   6   7  8  9  10  11  12  13  14  15
149     0, 8, 4, 12, 2, 10, 6, 14, 1, 9,  5, 13,  3, 11,  7, 15};
150 
151   return (revTab[(x&0xf)]<<4) | revTab[((x>>4)&0xf)];
152 
153 }
154 
155 /*****************************************************************************
156  *
157  * Extract the image data in 'data' which is in standard bitmap format to bitmap
158  * data in idata.  The image in data is WxH.
159  *
160  * Parametes:
161  *     idata		Extracted data
162  *     data             Data to be extracted in X11 bitmap format.
163  *     W                Width of buffer
164  *     H                Height of buffer
165  *     bpl              Bytes per line.
166  *
167  *****************************************************************************/
extractImageData(char * idata,const char * data,unsigned W,unsigned H,int bpl)168 static void extractImageData(char *idata,const char *data,unsigned W,unsigned H,int bpl)
169 {
170   const char *p;
171   int x,y;
172   unsigned byte;
173   int bw = (W+7) >> 3;
174 
175   p = strchr(data,'{');
176   if (!p) {
177     return;
178   }
179 
180   p++;
181   x = y = 0;
182   for (;;p++) {
183     if (!*p) {
184       return;
185     }
186     if (sscanf(p,"0x%x",&byte) == 1) {
187       if (TkGate.bitorder == MSBFirst)
188 	byte = reverseBits(byte);
189       idata[y*bpl+x] = byte;
190       x++;
191       if (x >= bw) {
192 	x = 0;
193 	y++;
194       }
195       if (y >= H) break;
196     }
197   }
198 }
199 
200 /*
201  * Create the rotations of the standard orientation image.
202  */
makeRotations(XImage * image,unsigned yoffset,unsigned W,unsigned H)203 static void makeRotations(XImage *image,unsigned yoffset,unsigned W,unsigned H)
204 {
205   int x,y;
206 
207   for (x = 0;x < W;x++)
208     for (y = 0;y < H;y++) {
209       int p = XGetPixel(image,x,y+yoffset);
210       if (p) {
211 	/*
212 	 * Assume we have already cleared the entire ximage and only need to set those
213 	 * pixels that are set.
214 	 */
215 	XPutPixel(image,W+y,	yoffset+W-x-1,	1);	/* orientation 1 */
216 	XPutPixel(image,W+H-x-1,yoffset+W+H-y-1,1);	/* orientation 2 */
217 	XPutPixel(image,H-y-1,	yoffset+H+x,	1);	/* orientation 3 */
218       }
219     }
220 }
221 
222 /*
223  * Create a new MssSymbol with the given identifier, normal icon data and select icon data.
224  */
new_MssSymbol(unsigned gid,GMIconData * normal,GMIconData * select)225 static MssSymbol *new_MssSymbol(unsigned gid,GMIconData *normal,GMIconData *select)
226 {
227   int i;
228   MssSymbol *me = (MssSymbol *) malloc(sizeof(MssSymbol));
229   unsigned cwidth,cheight;		/* Cell width and height */
230   unsigned width,height;		/* Total width and height */
231   XImage *image;
232   char *idata;
233   int boldOffset;
234   int bpl;
235   int idata_len;
236   int xoffset[4],yoffset[4];
237 
238   me->me_gid = gid;
239   me->me_next = 0;
240   me->me_luNext = 0;
241   me->me_luPrev = 0;
242 
243   /*
244    * Setup sizing information for icons
245    */
246   cwidth = imax(normal->w,select->w);
247   cheight = imax(normal->h,select->h);
248 
249   width = cwidth + cheight + 1;
250   width = (width+7) & ~0x7;				/* Round up to multiple of 8 */
251   height = 2*(cwidth + cheight + 1) + 1;
252   bpl = width >> 3;
253   boldOffset = cwidth + cheight + 1;
254 
255   /*
256    * Create image structure
257    */
258   idata = malloc(height*bpl);
259   idata_len = height*bpl;
260   for (i = 0;i < idata_len;i++)
261     idata[i] = 0;
262 
263   extractImageData(idata,normal->data,normal->w,normal->h,bpl);
264   extractImageData(idata+boldOffset*bpl,select->data,select->w,select->h,bpl);
265 
266   image = XCreateImage(TkGate.D,					/* Display */
267 		       DefaultVisualOfScreen(TkGate.S),		/* Visual */
268 		       1,					/* Depth */
269 		       XYPixmap,				/* format */
270 		       0,					/* offset */
271 		       idata,					/* data */
272 		       width,height,				/* width and height */
273 		       8,					/* bitmap pad */
274 		       0);					/* bytes per line */
275 
276   if (!image) {
277     logError(ERL_ERROR,"XCreateImage(%d,%d) failed.",width,height);
278     return 0;
279   }
280 
281   makeRotations(image,0,cwidth,cheight);
282   makeRotations(image,boldOffset,cwidth,cheight);
283 
284   me->me_pixmap = XCreatePixmap(TkGate.D,TkGate.root,width,height,1);
285   XPutImage(TkGate.D,me->me_pixmap,TkGate.bitGC,image,0,0,0,0,width,height);
286 
287   Pixmap_initZoomSet(me->me_pixmap,width,height);
288 
289   xoffset[0] = 0; 	yoffset[0] = 0;
290   xoffset[1] = cwidth;	yoffset[1] = 0;
291   xoffset[2] = cheight;	yoffset[2] = cwidth;
292   xoffset[3] = 0;	yoffset[3] = cheight;
293   for (i = 0;i < 4;i++) {
294     int W = (i&1) ? cheight : cwidth;
295     int H = (i&1) ? cwidth : cheight;
296 
297     me->me_normal[i] = new_Icon(me->me_pixmap,xoffset[i],yoffset[i],W,H,0,0);
298     me->me_select[i] = new_Icon(me->me_pixmap,xoffset[i],yoffset[i]+boldOffset,W,H,0,0);
299   }
300 
301   XDestroyImage(image);
302 
303   return me;
304 }
305 
306 /*
307  * Delete and MssSymbol object.
308  */
delete_MssSymbol(MssSymbol * me)309 static void delete_MssSymbol(MssSymbol *me)
310 {
311   int i;
312 
313   printf("delete_MssSymbol(%p)\n",me);
314 
315   if (me->me_pixmap != None) {
316     Pixmap_deleteZoomSet(me->me_pixmap);
317   }
318 
319   for (i = 0;i < 4;i++) {
320     if  (me->me_normal[i])
321       free(me->me_normal[i]);
322     if  (me->me_select[i])
323       free(me->me_select[i]);
324   }
325   free(me);
326 }
327 
328 /*
329  * Register a new MssSymbol object with the given normal and select icon data.  Return the
330  * identifier for the new object.
331  */
MSS_register(GMIconData * normalData,GMIconData * selectData)332 static unsigned MSS_register(GMIconData *normalData,GMIconData *selectData)
333 {
334   MssSymbol *me = new_MssSymbol(++mss.mss_idCount,normalData,selectData);
335   unsigned k = mss.mss_idCount & (MSS_SIZE-1);
336 
337   /*
338    * Insert into lookup bucket
339    */
340   me->me_next = mss.mss_ents[k];
341   mss.mss_ents[k] = me;
342 
343 
344   /*
345    * Insert into most-recently-used list.
346    */
347   me->me_luNext = mss.mss_mru;
348   if (mss.mss_mru) {
349     mss.mss_mru->me_luPrev = me;
350   }
351   mss.mss_mru = me;
352   if (!mss.mss_lru) mss.mss_lru = me;
353   mss.mss_numEntries++;
354 
355   if (mss.mss_numEntries > MSS_MAXENTRIES) {
356     MssSymbol *xe = mss.mss_lru;
357     mss.mss_lru = xe->me_luPrev;
358     mss.mss_lru->me_luNext = 0;
359     delete_MssSymbol(xe);
360     mss.mss_numEntries--;
361   }
362 
363   return mss.mss_idCount;
364 }
365 
366 /*
367  * Find the MssSymbol object with the given identifier.
368  */
MSS_find(unsigned gid)369 static MssSymbol *MSS_find(unsigned gid)
370 {
371   unsigned k = gid & (MSS_SIZE-1);
372   MssSymbol *e;
373 
374   for (e = mss.mss_ents[k];e;e = e->me_next) {
375     if (e->me_gid == gid)
376       return e;
377   }
378   return 0;
379 }
380 
381 /*
382  * Lookup the Icon object with the given identifier (gid), orientation (r) and boldness (isBold).
383  */
MSS_lookup(int gid,int r,int isBold)384 static Icon *MSS_lookup(int gid,int r,int isBold)
385 {
386   MssSymbol *e = 0;
387 
388   if (gid == 0) return 0;
389   e = MSS_find(gid);
390   if (!e) return 0;
391 
392   /*
393    * Update usage position
394    */
395 #if 0
396   if (e->me_luNext)
397     e->me_luNext->me_luPrev = e->me_luPrev;
398   else
399     mss.mss_lru = e->me_luPrev;
400 
401   if (e->me_luPrev)
402     e->me_luPrev->me_luNext = e->me_luNext;
403   else
404     mss.mss_mru = e->me_luNext;
405 
406   e->me_luPrev = 0;
407   e->me_luNext = mss.mss_mru;
408   mss.mss_mru = e;
409 #endif
410 
411   return isBold ? e->me_select[r] :  e->me_normal[r];
412 }
413 
414 /*
415  * Create a port for a GModSymbol
416  */
new_GSymPort(const char * name,int x,int y,int t,int r,int s)417 GSymPort *new_GSymPort(const char *name,int x,int y,int t,int r,int s)
418 {
419   GSymPort *msp;
420   msp = (GSymPort*) ob_malloc(sizeof(GSymPort),"GSymPort");
421   msp->msp_name = ob_strdup(name);
422   msp->msp_x = x;
423   msp->msp_y = y;
424   msp->msp_type = t;
425   msp->msp_orient = r;
426   msp->msp_size = s;
427 
428   return msp;
429 }
430 
431 /*
432  * Initialize the module symbol server.
433  */
MSS_init()434 void MSS_init()
435 {
436   int i;
437 
438   mss.mss_idCount = 0;
439   mss.mss_numEntries = 0;
440   mss.mss_mru = 0;
441   mss.mss_lru = 0;
442 
443   for (i = 0;i < MSS_SIZE;i++)
444     mss.mss_ents[i] = 0;
445 }
446 
447 
delete_GSymPort(GSymPort * msp)448 void delete_GSymPort(GSymPort *msp)
449 {
450   ob_free(msp->msp_name);
451   ob_free(msp);
452 }
453 
GMIconData_init(GMIconData * id)454 void GMIconData_init(GMIconData *id)
455 {
456   id->data = ob_strdup("");
457   id->x = id->y = 0;
458   id->w = id->h = 0;
459 }
460 
GMIconData_copy(GMIconData * id,GMIconData * src_id)461 void GMIconData_copy(GMIconData *id,GMIconData *src_id)
462 {
463   id->data = ob_strdup(src_id->data);
464   id->x = src_id->x;
465   id->y = src_id->y;
466   id->w = src_id->w;
467   id->h = src_id->h;
468 }
469 
GMIconData_uninit(GMIconData * id)470 void GMIconData_uninit(GMIconData *id)
471 {
472   ob_free(id->data);
473   id->data = 0;
474 }
475 
GMIconData_set(GMIconData * id,const char * data,int x,int y)476 void GMIconData_set(GMIconData *id,const char *data,int x,int y)
477 {
478   unsigned w,h;
479 
480   ob_free(id->data);
481   id->data = ob_strdup(data);
482   id->x = x;
483   id->y = y;
484 
485   if (sscanf(data,"%*s %*s %u %*s %*s %u",&w,&h) == 2) {
486     id->w = w;
487     id->h = h;
488   } else {
489     id->w = 0;
490     id->h = 0;
491   }
492 }
493 
494 /*
495  * Create a new module symbol
496  */
new_GModSymbol()497 GModSymbol *new_GModSymbol()
498 {
499   GModSymbol *ms;
500   int i;
501 
502   ms = (GModSymbol*) ob_malloc(sizeof(GModSymbol),"GModSymbol");
503   ms->ms_gid = 0;
504   ms->ms_refCount = 0;
505   ms->ms_numPorts = 0;
506   ms->ms_ports = 0;
507   for (i = 0;i < 4;i++) {
508     ms->ms_ix[0][i] = ms->ms_iy[0][i] = 0;
509     ms->ms_ix[1][i] = ms->ms_iy[1][i] = 0;
510   }
511 
512   GMIconData_init(&ms->ms_normal);
513   GMIconData_init(&ms->ms_select);
514 
515   if (!symbolTable) symbolTable = new_PHash();
516   PHash_insert(symbolTable,ms,ms);
517 
518   GModSymbol_setNormalIcon(ms, defaultSymbol_data, defaultSymbol_x, defaultSymbol_y);
519   GModSymbol_setSelectIcon(ms, defaultBoldSymbol_data, defaultSymbol_x, defaultSymbol_y);
520 
521   return ms;
522 }
523 
524 /*
525  * Create a new module symbol
526  */
copy_GModSymbol(GModSymbol * src_ms)527 GModSymbol *copy_GModSymbol(GModSymbol *src_ms)
528 {
529   GModSymbol *ms;
530   int i;
531 
532 
533   ms = (GModSymbol*) ob_malloc(sizeof(GModSymbol),"GModSymbol");
534   ms->ms_gid = 0;
535   ms->ms_refCount = 0;
536   ms->ms_numPorts = 0;
537   ms->ms_ports = 0;
538   for (i = 0;i < 4;i++) {
539     ms->ms_ix[0][i] = src_ms->ms_ix[0][i];
540     ms->ms_ix[1][i] = src_ms->ms_ix[1][i];
541     ms->ms_iy[0][i] = src_ms->ms_iy[0][i];
542     ms->ms_iy[1][i] = src_ms->ms_iy[1][i];
543   }
544 
545   GMIconData_copy(&ms->ms_normal,&src_ms->ms_normal);
546   GMIconData_copy(&ms->ms_select,&src_ms->ms_select);
547   ms->ms_gid = 0;
548   ms->ms_finalized = 0;
549 
550   for (i = 0;i < src_ms->ms_numPorts;i++) {
551     GSymPort *p = src_ms->ms_ports[i];
552     GModSymbol_addPort(ms,new_GSymPort(p->msp_name,p->msp_x,p->msp_y,p->msp_type,p->msp_orient,p->msp_size));
553   }
554 
555   if (!symbolTable) symbolTable = new_PHash();
556   PHash_insert(symbolTable,ms,ms);
557 
558 #if DEBUG_MOD_SYM
559   {
560     char buf[STRMAX];
561     sprintf(buf,"%p - rc=%d gid=%d nports=%d",ms,ms->ms_refCount,ms->ms_gid,ms->ms_numPorts);
562     DoTclL("DebugModSym::add",buf,NULL);
563   }
564 #endif
565 
566   return ms;
567 }
568 
569 /*
570  * Delete the module symbol
571  */
delete_GModSymbol(GModSymbol * ms)572 void delete_GModSymbol(GModSymbol *ms)
573 {
574   GMIconData_uninit(&ms->ms_normal);
575   GMIconData_uninit(&ms->ms_select);
576   GModSymbol_flushPorts(ms);
577 
578 #if DEBUG_MOD_SYM
579   {
580     char buf[STRMAX];
581     sprintf(buf,"%p - rc=%d gid=%d nports=%d",ms,ms->ms_refCount,ms->ms_gid,ms->ms_numPorts);
582     DoTclL("DebugModSym::del",buf,NULL);
583   }
584 #endif
585 
586   ob_free(ms);
587 
588   if (!symbolTable) symbolTable = new_PHash();
589   PHash_remove(symbolTable,ms);
590 }
591 
GModSymbol_attach(GModSymbol * ms)592 void GModSymbol_attach(GModSymbol *ms)
593 {
594   ob_touch(ms);
595   ms->ms_refCount++;
596 
597 #if DEBUG_MOD_SYM
598   {
599     char buf[STRMAX];
600     sprintf(buf,"%p - rc=%d gid=%d nports=%d",ms,ms->ms_refCount,ms->ms_gid,ms->ms_numPorts);
601     DoTclL("DebugModSym::update",buf,NULL);
602   }
603 #endif
604 }
605 
GModSymbol_detach(GModSymbol * ms)606 void GModSymbol_detach(GModSymbol *ms)
607 {
608   ob_touch(ms);
609   if (--ms->ms_refCount <= 0) {
610     delete_GModSymbol(ms);
611   } else {
612 #if DEBUG_MOD_SYM
613     char buf[STRMAX];
614     sprintf(buf,"%p - rc=%d gid=%d nports=%d",ms,ms->ms_refCount,ms->ms_gid,ms->ms_numPorts);
615     DoTclL("DebugModSym::update",buf,NULL);
616 #endif
617   }
618 }
619 
620 /*
621  * Flush all of the module ports
622  */
GModSymbol_flushPorts(GModSymbol * ms)623 void GModSymbol_flushPorts(GModSymbol *ms)
624 {
625   int i;
626 
627   ob_touch(ms);
628   for (i = 0;i < ms->ms_numPorts;i++)
629     delete_GSymPort(ms->ms_ports[i]);
630   if (ms->ms_ports) ob_free(ms->ms_ports);
631   ms->ms_numPorts = 0;
632   ms->ms_ports = 0;
633 
634 #if DEBUG_MOD_SYM
635   {
636     char buf[STRMAX];
637     sprintf(buf,"%p - rc=%d gid=%d nports=%d",ms,ms->ms_refCount,ms->ms_gid,ms->ms_numPorts);
638     DoTclL("DebugModSym::update",buf,NULL);
639   }
640 #endif
641 }
642 
GModSymbol_updateCenter(GModSymbol * ms)643 static void GModSymbol_updateCenter(GModSymbol *ms)
644 {
645   int minx = imin(ms->ms_normal.x, ms->ms_select.x);
646   int miny = imin(ms->ms_normal.y, ms->ms_select.y);
647   int maxx = imax(ms->ms_normal.x + ms->ms_normal.w, ms->ms_select.x + ms->ms_select.w);
648   int maxy = imax(ms->ms_normal.y + ms->ms_normal.h, ms->ms_select.y + ms->ms_select.h);
649   //  int width = maxx - minx - 1;
650   //  int height = maxy - miny - 1;
651   int i,j;
652 
653   ob_touch(ms);
654 
655 #if 0
656   printf("updateCenter %dx%d  N:%dx%d  S:%dx%d\n",
657 	 width,height,
658 	 ms->ms_normal.w,ms->ms_normal.h,
659 	 ms->ms_select.w,ms->ms_select.h
660 	 );
661 #endif
662 
663   ms->ms_cx = (maxx+minx)/2;
664   ms->ms_cy = (maxy+miny)/2;
665 
666   ms->ms_basex = minx;
667   ms->ms_basey = miny;
668 
669   ms->ms_ix[0][0] = ms->ms_normal.x - ms->ms_cx;
670   ms->ms_iy[0][0] = ms->ms_normal.y - ms->ms_cy;
671   ms->ms_ix[1][0] = ms->ms_select.x - ms->ms_cx;
672   ms->ms_iy[1][0] = ms->ms_select.y - ms->ms_cy;
673 
674   ms->ms_ix[0][1] = ms->ms_normal.x + ms->ms_normal.w - ms->ms_cx - 1;
675   ms->ms_iy[0][1] = ms->ms_normal.y - ms->ms_cy;
676   ms->ms_ix[1][1] = ms->ms_select.x + ms->ms_select.w - ms->ms_cx - 1;
677   ms->ms_iy[1][1] = ms->ms_select.y - ms->ms_cy;
678 
679   ms->ms_ix[0][2] = ms->ms_normal.x + ms->ms_normal.w - ms->ms_cx - 1;
680   ms->ms_iy[0][2] = ms->ms_normal.y + ms->ms_normal.h - ms->ms_cy - 1;
681   ms->ms_ix[1][2] = ms->ms_select.x + ms->ms_select.w - ms->ms_cx - 1;
682   ms->ms_iy[1][2] = ms->ms_select.y + ms->ms_select.h - ms->ms_cy - 1;
683 
684   ms->ms_ix[0][3] = ms->ms_normal.x - ms->ms_cx;
685   ms->ms_iy[0][3] = ms->ms_normal.y + ms->ms_normal.h - ms->ms_cy - 1;
686   ms->ms_ix[1][3] = ms->ms_select.x - ms->ms_cx;
687   ms->ms_iy[1][3] = ms->ms_normal.y + ms->ms_normal.h - ms->ms_cy - 1;
688 
689   for (i = 1;i < 4;i++) {
690     rotatePoint(&ms->ms_ix[0][i],&ms->ms_iy[0][i],0,0,i);
691     rotatePoint(&ms->ms_ix[1][i],&ms->ms_iy[1][i],0,0,i);
692   }
693 
694 
695   for (i = 0;i < ms->ms_numPorts;i++) {
696     GSymPort *msp = ms->ms_ports[i];
697 
698     for (j = 0;j < 4;j++) {
699       GPadLoc *l = &msp->msp_loc[j];
700       int x = msp->msp_x - ms->ms_cx;
701       int y = msp->msp_y - ms->ms_cy;
702 
703       rotatePoint(&x,&y,0,0,j);
704       l->x1 = l->x2 = x;
705       l->y1 = l->y2 = y;
706       l->dir = (msp->msp_orient + j) % 4;
707     }
708   }
709 
710   ms->ms_finalized = 1;
711 }
712 
713 /*
714  * Add a port to a module
715  */
GModSymbol_addPort(GModSymbol * ms,GSymPort * p)716 void GModSymbol_addPort(GModSymbol *ms,GSymPort *p)
717 {
718 #if 0
719   printf("addPort %s[%d]\n",p->msp_name,p->msp_size);
720 #endif
721 
722   ob_touch(ms);
723   if ((ms->ms_numPorts % MSP_STEPSIZE) == 0) {
724     if (ms->ms_numPorts > 0)
725       ms->ms_ports = ob_realloc(ms->ms_ports,
726 				sizeof(GSymPort*)*(ms->ms_numPorts+MSP_STEPSIZE));
727     else
728       ms->ms_ports = ob_malloc(sizeof(GSymPort*)*MSP_STEPSIZE,"GSymPort*");
729   }
730   ob_touch(ms->ms_ports);
731   ms->ms_ports[ms->ms_numPorts++] = p;
732 
733   ms->ms_finalized = 0;
734 
735 #if DEBUG_MOD_SYM
736   {
737     char buf[STRMAX];
738     sprintf(buf,"%p - rc=%d gid=%d nports=%d",ms,ms->ms_refCount,ms->ms_gid,ms->ms_numPorts);
739     DoTclL("DebugModSym::update",buf,NULL);
740   }
741 #endif
742 }
743 
GModSymbol_setNormalIcon(GModSymbol * ms,const char * data,int x,int y)744 void GModSymbol_setNormalIcon(GModSymbol *ms,const char *data,int x,int y)
745 {
746   ob_touch(ms);
747   GMIconData_set(&ms->ms_normal,data,x,y);
748   ms->ms_gid = 0;
749   ms->ms_finalized = 0;
750 }
751 
GModSymbol_setSelectIcon(GModSymbol * ms,const char * data,int x,int y)752 void GModSymbol_setSelectIcon(GModSymbol *ms,const char *data,int x,int y)
753 {
754   ob_touch(ms);
755   GMIconData_set(&ms->ms_select,data,x,y);
756   ms->ms_gid = 0;
757   ms->ms_finalized = 0;
758 }
759 
GModSymbol_getNormalIcon(GModSymbol * ms,int * x,int * y)760 const char *GModSymbol_getNormalIcon(GModSymbol *ms,int *x,int *y)
761 {
762   *x = ms->ms_normal.x;
763   *y = ms->ms_normal.y;
764   return ms->ms_normal.data;
765 }
766 
GModSymbol_getSelectIcon(GModSymbol * ms,int * x,int * y)767 const char *GModSymbol_getSelectIcon(GModSymbol *ms,int *x,int *y)
768 {
769   *x = ms->ms_select.x;
770   *y = ms->ms_select.y;
771   return ms->ms_select.data;
772 }
773 
774 /*
775  * Get the icon for a symbol with orientation r, and boldness isBold.
776  */
GModSymbol_getIcon(GModSymbol * ms,int r,int isBold)777 static Icon *GModSymbol_getIcon(GModSymbol *ms,int r,int isBold)
778 {
779   Icon *I = 0;
780 
781   I = MSS_lookup(ms->ms_gid,r,isBold);
782   if (!I) {
783     ms->ms_gid = MSS_register(&ms->ms_normal,&ms->ms_select);
784     I = MSS_lookup(ms->ms_gid,r,isBold);
785 #if 0
786     printf("gotIcon: (%d, %d) %dx%d pm=%x\n",I->x,I->y,I->width,I->height,(unsigned)I->pm);
787 #endif
788   }
789 
790 
791   return I;
792 }
793 
794 /*****************************************************************************
795  *
796  * Get the extents of a module symbol
797  *
798  * Parameters:
799  *    ms		Symbol to get extentds of
800  *    *minx		Return for minimum x value
801  *    *miny		Return for minimum y value
802  *    *maxx		Return for maximum x value
803  *    *maxy		Return for maximum y value
804  *
805  *****************************************************************************/
GModSymbol_getExtents(GModSymbol * ms,int r,int * minx,int * miny,int * maxx,int * maxy)806 void GModSymbol_getExtents(GModSymbol *ms,int r,int *minx,int *miny,int *maxx,int *maxy)
807 {
808   int w = ms->ms_normal.w;
809   int h = ms->ms_normal.h;
810 
811   *minx = ms->ms_ix[0][r];
812   *miny = ms->ms_iy[0][r];
813   *maxx = ms->ms_ix[0][r] + w;
814   *maxy = ms->ms_iy[0][r] + h;
815 }
816 
817 /*****************************************************************************
818  *
819  * Draw a symbol at the specified position.
820  *
821  * Parameters:
822  *      ms		Symbol to draw
823  *      x		x-coordinate at which to draw symbol
824  *      y		y-coordinate at which to draw symbol
825  *      r		rotation for symbol
826  *      isBold		Non-zero for bold version of symbol
827  *
828  *****************************************************************************/
GModSymbol_draw(GModSymbol * ms,int x,int y,int r,int isBold)829 void GModSymbol_draw(GModSymbol *ms,int x,int y,int r,int isBold)
830 {
831   Icon *I = GModSymbol_getIcon(ms,r,isBold);
832   int ix,iy;
833 
834   isBold = (isBold != 0);	/* Make sure isBold is only 0 or 1 */
835 
836 #if 0
837   printf("GModSymbol_draw(x=%d, y=%d, r=%d, b=%d)\n",x,y,r,isBold);
838 #endif
839 
840   if (!ms->ms_finalized) GModSymbol_updateCenter(ms);
841 
842   ix = ctow_x(x) + ms->ms_ix[isBold][r];
843   iy = ctow_y(y) + ms->ms_iy[isBold][r];
844 
845   Icon_draw(TkGate.D,TkGate.W,TkGate.moduleGC,ix,iy,I);
846 }
847 
GModSymbol_first()848 HashElem *GModSymbol_first()
849 {
850   if (!symbolTable)
851     return 0;
852   else
853     return Hash_first(symbolTable);
854 }
855 
GModSymbol_next(HashElem * e)856 HashElem *GModSymbol_next(HashElem *e)
857 {
858   if (!symbolTable)
859     return 0;
860   else
861     return Hash_next(symbolTable,e);
862 }
863 
864 
GModSymbol_numPorts(GModSymbol * ms)865 int GModSymbol_numPorts(GModSymbol *ms)
866 {
867   if (!ms->ms_finalized) GModSymbol_updateCenter(ms);
868   return ms->ms_numPorts;
869 }
870 
GModSymbol_getPort(GModSymbol * ms,int p)871 GSymPort *GModSymbol_getPort(GModSymbol *ms,int p)
872 {
873   if (!ms->ms_finalized) GModSymbol_updateCenter(ms);
874   return ms->ms_ports[p];
875 }
876