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