~ubuntu-branches/ubuntu/jaunty/electric/jaunty

« back to all changes in this revision

Viewing changes to src/cons/conlay.c

  • Committer: Bazaar Package Importer
  • Author(s): Onkar Shinde
  • Date: 2009-01-08 02:05:08 UTC
  • mfrom: (1.3.1 upstream) (3.1.3 sid)
  • mto: (3.1.4 sid)
  • mto: This revision was merged to the branch mainline in revision 11.
  • Revision ID: james.westby@ubuntu.com-20090108020508-3e7e6241i7bkit2l
New upstream version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Electric(tm) VLSI Design System
3
 
 *
4
 
 * File: conlay.c
5
 
 * Hierarchical layout constraint system
6
 
 * Written by: Steven M. Rubin, Static Free Software
7
 
 *
8
 
 * Copyright (c) 2001 Static Free Software
9
 
 *
10
 
 * Electric(tm) is free software; you can redistribute it and/or modify
11
 
 * it under the terms of the GNU General Public License as published by
12
 
 * the Free Software Foundation; either version 2 of the License, or
13
 
 * (at your option) any later version.
14
 
 *
15
 
 * Electric(tm) is distributed in the hope that it will be useful,
16
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 
 * GNU General Public License for more details.
19
 
 *
20
 
 * You should have received a copy of the GNU General Public License
21
 
 * along with Electric(tm); see the file COPYING.  If not, write to
22
 
 * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23
 
 * Boston, Mass 02111-1307, USA.
24
 
 *
25
 
 * Static Free Software
26
 
 * 4119 Alpine Road
27
 
 * Portola Valley, California 94028
28
 
 * info@staticfreesoft.com
29
 
 */
30
 
#include "global.h"
31
 
#include "conlay.h"
32
 
#include "database.h"
33
 
#include "usr.h"
34
 
 
35
 
/* working memory for "cla_modwithin()" */
36
 
static INTBIG    cla_workingarccount = 0;
37
 
static ARCINST **cla_workingarcs;
38
 
 
39
 
/* routines referenced in "conlin.c"*/
40
 
void cla_oldportposition(NODEINST*, PORTPROTO*, INTBIG*, INTBIG*);
41
 
void cla_adjustmatrix(NODEINST*, PORTPROTO*, XARRAY);
42
 
 
43
 
/* prototypes for local routines */
44
 
static BOOLEAN cla_modifynodeinst(NODEINST *ni, INTBIG deltalx, INTBIG deltaly, INTBIG deltahx,
45
 
                                INTBIG deltahy, INTBIG dangle, INTBIG dtrans, BOOLEAN announce);
46
 
static BOOLEAN cla_modnodearcs(NODEINST*, INTBIG, INTBIG);
47
 
static void cla_modwithin(NODEINST*, INTBIG, INTBIG);
48
 
static BOOLEAN cla_modrigid(NODEINST*, INTBIG, INTBIG);
49
 
static BOOLEAN cla_modflex(NODEINST*, INTBIG, INTBIG);
50
 
static void cla_nonorthogfixang(ARCINST*, INTBIG, INTBIG, NODEINST*, INTBIG[2], INTBIG[2]);
51
 
static void cla_ensurearcinst(ARCINST*, INTBIG);
52
 
static void cla_updatearc(ARCINST*, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG);
53
 
static void cla_domovearcinst(ARCINST*, INTBIG, INTBIG, INTBIG, INTBIG, INTBIG);
54
 
static void cla_makeoldrot(NODEINST*, XARRAY);
55
 
static void cla_makeoldtrans(NODEINST*, XARRAY);
56
 
static void cla_computefacet(NODEPROTO*, BOOLEAN);
57
 
static BOOLEAN cla_lookdown(NODEPROTO*);
58
 
 
59
 
#define CLA_DEBUG 1                     /* comment out for normal life */
60
 
 
61
 
/* command completion table for this constraint solver */
62
 
static KEYWORD layconopt[] =
63
 
{
64
 
        {"debug-toggle",      0,{NOKEY,NOKEY,NOKEY,NOKEY,NOKEY}},
65
 
        TERMKEY
66
 
};
67
 
COMCOMP cla_layconp = {layconopt, NOTOPLIST, NONEXTLIST, NOPARAMS, NOBACKUP,
68
 
        0, " \t", M_("layout constraint system option"), 0};
69
 
 
70
 
INTBIG cla_changeclock;
71
 
#ifdef CLA_DEBUG
72
 
static BOOLEAN cla_conlaydebug;
73
 
#endif
74
 
CONSTRAINT *cla_constraint;     /* the constraint object for this solver */
75
 
 
76
 
/******************** CONSTRAINT SYSTEM HOOKS *************************/
77
 
 
78
 
void cla_layconinit(CONSTRAINT *con)
79
 
{
80
 
        /* only function during pass 1 of initialization */
81
 
        if (con == NOCONSTRAINT) return;
82
 
        cla_constraint = con;
83
 
        cla_changeclock = 10;
84
 
#ifdef CLA_DEBUG
85
 
        cla_conlaydebug = FALSE;
86
 
#endif
87
 
}
88
 
 
89
 
void cla_layconterm(void)
90
 
{
91
 
        if (cla_workingarccount > 0) efree((char *)cla_workingarcs);
92
 
        cla_workingarccount = 0;
93
 
}
94
 
 
95
 
void cla_layconsetmode(INTBIG count, char *par[])
96
 
{
97
 
        REGISTER INTBIG l;
98
 
        REGISTER char *pp;
99
 
 
100
 
        if (count == 0)
101
 
        {
102
 
                ttyputusage("constraint tell layout OPTION");
103
 
                return;
104
 
        }
105
 
 
106
 
        if (el_curconstraint != cla_constraint)
107
 
        {
108
 
                ttyputerr(M_("Must first switch to this solver with 'constraint use'"));
109
 
                return;
110
 
        }
111
 
 
112
 
        l = strlen(pp = par[0]);
113
 
 
114
 
        /* debugging switch */
115
 
        if (namesamen(pp, "debug-toggle", l) == 0 && l >= 1)
116
 
        {
117
 
#ifdef CLA_DEBUG
118
 
                cla_conlaydebug = !cla_conlaydebug;
119
 
                if (cla_conlaydebug) ttyputmsg(M_("Layout constraint debugging on")); else
120
 
                        ttyputmsg(M_("Layout constraint debugging off"));
121
 
#else
122
 
                ttyputmsg(M_("Sorry, constraint debugging code has been compiled out"));
123
 
#endif
124
 
                return;
125
 
        }
126
 
        ttyputbadusage("constraint tell layout");
127
 
}
128
 
 
129
 
/*
130
 
 * the valid "command" is "describearc" which returns a string that describes
131
 
 * the constraints on the arc in "arg1".
132
 
 */
133
 
INTBIG cla_layconrequest(char *command, INTBIG arg1)
134
 
{
135
 
        REGISTER ARCINST *ai;
136
 
        REGISTER INTBIG l;
137
 
 
138
 
        l = strlen(command);
139
 
 
140
 
        if (namesamen(command, "describearc", l) == 0)
141
 
        {
142
 
                ai = (ARCINST *)arg1;
143
 
                (void)initinfstr();
144
 
                if ((ai->userbits&FIXED) != 0) (void)addtoinfstr('R'); else
145
 
                {
146
 
                        switch (ai->userbits&(FIXANG|CANTSLIDE))
147
 
                        {
148
 
                                case 0:                (void)addtoinfstr('S');         break;
149
 
                                case FIXANG:           (void)addstringtoinfstr("FS");  break;
150
 
                                case CANTSLIDE:        (void)addtoinfstr('X');         break;
151
 
                                case FIXANG|CANTSLIDE: (void)addtoinfstr('F');         break;
152
 
                        }
153
 
                }
154
 
                return((INTBIG)returninfstr());
155
 
        }
156
 
        return(0);
157
 
}
158
 
 
159
 
/*
160
 
 * routine to do hierarchical update on any facets that changed
161
 
 */
162
 
void cla_layconsolve(NODEPROTO *np)
163
 
{
164
 
        REGISTER CHANGEFACET *cc;
165
 
        REGISTER CHANGEBATCH *curbatch;
166
 
        REGISTER CHANGE *c;
167
 
 
168
 
        /* if only one facet is requested, solve that */
169
 
        curbatch = db_getcurrentbatch();
170
 
        if (np != NONODEPROTO)
171
 
        {
172
 
                cla_computefacet(np, FALSE);
173
 
        } else
174
 
        {
175
 
                /* solve all facets that changed */
176
 
                if (curbatch != NOCHANGEBATCH)
177
 
                        for(cc = curbatch->firstchangefacet; cc != NOCHANGEFACET; cc = cc->nextchangefacet)
178
 
                                cla_computefacet(cc->changefacet, cc->forcedlook);
179
 
        }
180
 
 
181
 
        if (curbatch == NOCHANGEBATCH) return;
182
 
        for(c = curbatch->changehead; c != NOCHANGE; c = c->nextchange)
183
 
                switch (c->changetype)
184
 
        {
185
 
                case NODEINSTNEW:
186
 
                case NODEINSTKILL:
187
 
                case NODEINSTMOD:
188
 
                        ((NODEINST *)c->entryaddr)->changeaddr = (char *)NOCHANGE;
189
 
                        break;
190
 
                case ARCINSTNEW:
191
 
                case ARCINSTKILL:
192
 
                case ARCINSTMOD:
193
 
                        ((ARCINST *)c->entryaddr)->changeaddr = (char *)NOCHANGE;
194
 
                        break;
195
 
                case PORTPROTONEW:
196
 
                case PORTPROTOKILL:
197
 
                case PORTPROTOMOD:
198
 
                        ((PORTPROTO *)c->entryaddr)->changeaddr = (char *)NOCHANGE;
199
 
                        break;
200
 
                case NODEPROTONEW:
201
 
                case NODEPROTOKILL:
202
 
                case NODEPROTOMOD:
203
 
                        ((NODEPROTO *)c->entryaddr)->changeaddr = (char *)NOCHANGE;
204
 
                        break;
205
 
        }
206
 
}
207
 
 
208
 
/*
209
 
 * If an export is created, touch all instances of the facet
210
 
 */
211
 
void cla_layconnewobject(INTBIG addr, INTBIG type)
212
 
{
213
 
        REGISTER NODEPROTO *np;
214
 
        REGISTER PORTPROTO *pp;
215
 
        REGISTER NODEINST *ni;
216
 
 
217
 
        if (type == VPORTPROTO)
218
 
        {
219
 
                pp = (PORTPROTO *)addr;
220
 
                np = pp->parent;
221
 
                for(ni = np->firstinst; ni != NONODEINST; ni = ni->nextinst)
222
 
                {
223
 
                        (void)db_change((INTBIG)ni, OBJECTSTART, VNODEINST, 0, 0, 0, 0, 0);
224
 
                        (void)db_change((INTBIG)ni, NODEINSTMOD, ni->lowx, ni->lowy,
225
 
                                ni->highx, ni->highy, ni->rotation, ni->transpose);
226
 
                        (void)db_change((INTBIG)ni, OBJECTEND, VNODEINST, 0, 0, 0, 0, 0);
227
 
                }
228
 
        }
229
 
}
230
 
 
231
 
/*
232
 
 * If an export is deleted, touch all instances of the facet
233
 
 */
234
 
void cla_layconkillobject(INTBIG addr, INTBIG type)
235
 
{
236
 
        REGISTER NODEPROTO *np;
237
 
        REGISTER PORTPROTO *pp;
238
 
        REGISTER NODEINST *ni;
239
 
 
240
 
        if (type == VPORTPROTO)
241
 
        {
242
 
                pp = (PORTPROTO *)addr;
243
 
                np = pp->parent;
244
 
                for(ni = np->firstinst; ni != NONODEINST; ni = ni->nextinst)
245
 
                {
246
 
                        (void)db_change((INTBIG)ni, OBJECTSTART, VNODEINST, 0, 0, 0, 0, 0);
247
 
                        (void)db_change((INTBIG)ni, NODEINSTMOD, ni->lowx, ni->lowy,
248
 
                                ni->highx, ni->highy, ni->rotation, ni->transpose);
249
 
                        (void)db_change((INTBIG)ni, OBJECTEND, VNODEINST, 0, 0, 0, 0, 0);
250
 
                }
251
 
        }
252
 
}
253
 
 
254
 
/*
255
 
 * If an export is renamed, touch all instances of the facet
256
 
 */
257
 
void cla_layconnewvariable(INTBIG addr, INTBIG type, INTBIG skey, INTBIG stype)
258
 
{
259
 
        char *name;
260
 
        REGISTER NODEPROTO *np;
261
 
        REGISTER PORTPROTO *pp;
262
 
        REGISTER NODEINST *ni;
263
 
 
264
 
        if (type == VPORTPROTO)
265
 
        {
266
 
                if ((stype&VCREF) != 0)
267
 
                {
268
 
                        name = changedvariablename(type, skey, stype);
269
 
                        if (strcmp(name, "protoname") == 0)
270
 
                        {
271
 
                                pp = (PORTPROTO *)addr;
272
 
                                np = pp->parent;
273
 
                                for(ni = np->firstinst; ni != NONODEINST; ni = ni->nextinst)
274
 
                                {
275
 
                                        (void)db_change((INTBIG)ni, OBJECTSTART, VNODEINST, 0, 0, 0, 0, 0);
276
 
                                        (void)db_change((INTBIG)ni, NODEINSTMOD, ni->lowx, ni->lowy,
277
 
                                                ni->highx, ni->highy, ni->rotation, ni->transpose);
278
 
                                        (void)db_change((INTBIG)ni, OBJECTEND, VNODEINST, 0, 0, 0, 0, 0);
279
 
                                }
280
 
                        }
281
 
                }
282
 
        }
283
 
}
284
 
 
285
 
/*
286
 
 * set layout constraints on arc instance "ai" according to "changetype".
287
 
 * the routine returns true if the arc change is not successful (or already
288
 
 * done)
289
 
 */
290
 
BOOLEAN cla_layconsetobject(INTBIG addr, INTBIG type, INTBIG changetype,
291
 
        INTBIG /*@unused@*/ changedata)
292
 
{
293
 
        REGISTER ARCINST *ai;
294
 
 
295
 
        if ((type&VTYPE) != VARCINST) return(TRUE);
296
 
        ai = (ARCINST *)addr;
297
 
        if (ai == NOARCINST) return(TRUE);
298
 
        switch (changetype)
299
 
        {
300
 
                case CHANGETYPERIGID:                           /* arc rigid */
301
 
                        if ((ai->userbits & FIXED) != 0) return(TRUE);
302
 
                        (void)setval((INTBIG)ai, VARCINST, "userbits", ai->userbits|FIXED, VINTEGER);
303
 
                        break;
304
 
                case CHANGETYPEUNRIGID:                         /* arc un-rigid */
305
 
                        if ((ai->userbits & FIXED) == 0) return(TRUE);
306
 
                        (void)setval((INTBIG)ai, VARCINST, "userbits", ai->userbits & ~FIXED, VINTEGER);
307
 
                        break;
308
 
                case CHANGETYPEFIXEDANGLE:                      /* arc fixed-angle */
309
 
                        if ((ai->userbits & FIXANG) != 0) return(TRUE);
310
 
                        (void)setval((INTBIG)ai, VARCINST, "userbits", ai->userbits|FIXANG, VINTEGER);
311
 
                        break;
312
 
                case CHANGETYPENOTFIXEDANGLE:           /* arc not fixed-angle */
313
 
                        if ((ai->userbits & FIXANG) == 0) return(TRUE);
314
 
                        (void)setval((INTBIG)ai, VARCINST, "userbits", ai->userbits & ~FIXANG, VINTEGER);
315
 
                        break;
316
 
                case CHANGETYPESLIDABLE:                        /* arc slidable */
317
 
                        if ((ai->userbits & CANTSLIDE) == 0) return(TRUE);
318
 
                        (void)setval((INTBIG)ai, VARCINST, "userbits", ai->userbits & ~CANTSLIDE, VINTEGER);
319
 
                        break;
320
 
                case CHANGETYPENOTSLIDABLE:                     /* arc nonslidable */
321
 
                        if ((ai->userbits & CANTSLIDE) != 0) return(TRUE);
322
 
                        (void)setval((INTBIG)ai, VARCINST, "userbits", ai->userbits|CANTSLIDE, VINTEGER);
323
 
                        break;
324
 
                case CHANGETYPETEMPRIGID:                       /* arc temporarily rigid */
325
 
                        if (ai->changed == cla_changeclock + 2) return(TRUE);
326
 
                        ai->changed = cla_changeclock + 2;
327
 
                        break;
328
 
                case CHANGETYPETEMPUNRIGID:                     /* arc temporarily un-rigid */
329
 
                        if (ai->changed == cla_changeclock + 3) return(TRUE);
330
 
                        ai->changed = cla_changeclock + 3;
331
 
                        break;
332
 
                case CHANGETYPEREMOVETEMP:                      /* remove temporarily state */
333
 
                        if (ai->changed != cla_changeclock + 3 && ai->changed != cla_changeclock + 2) return(TRUE);
334
 
                        ai->changed = cla_changeclock - 3;
335
 
                        break;
336
 
        }
337
 
        return(FALSE);
338
 
}
339
 
 
340
 
void cla_layconmodifynodeinst(NODEINST *ni, INTBIG dlx, INTBIG dly, INTBIG dhx, INTBIG dhy,
341
 
        INTBIG drot, INTBIG dtrans)
342
 
{
343
 
        /* advance the change clock */
344
 
        cla_changeclock += 4;
345
 
 
346
 
        /* change the nodeinst */
347
 
        if (cla_modifynodeinst(ni, dlx, dly, dhx, dhy, drot, dtrans, FALSE))
348
 
                db_forcehierarchicalanalysis(ni->parent);
349
 
 
350
 
        /* change the arcs on the nodeinst */
351
 
        if (cla_modnodearcs(ni, drot, dtrans))
352
 
                db_forcehierarchicalanalysis(ni->parent);
353
 
}
354
 
 
355
 
void cla_layconmodifynodeinsts(INTBIG count, NODEINST **nis, INTBIG *dlxs, INTBIG *dlys,
356
 
        INTBIG *dhxs, INTBIG *dhys, INTBIG *drots, INTBIG *dtranss)
357
 
{
358
 
        REGISTER INTBIG i;
359
 
        REGISTER NODEPROTO *parent;
360
 
 
361
 
        /* advance the change clock */
362
 
        cla_changeclock += 4;
363
 
 
364
 
        /* change the nodeinst */
365
 
        parent = NONODEPROTO;
366
 
        for(i=0; i<count; i++)
367
 
        {
368
 
                if (cla_modifynodeinst(nis[i], dlxs[i], dlys[i], dhxs[i], dhys[i],
369
 
                        drots[i], dtranss[i], FALSE)) parent = nis[i]->parent;
370
 
        }
371
 
 
372
 
        /* change the arcs on the nodeinst */
373
 
        for(i=0; i<count; i++)
374
 
        {
375
 
                if (cla_modnodearcs(nis[i], drots[i], dtranss[i]))
376
 
                        parent = nis[i]->parent;
377
 
        }
378
 
        if (parent != NONODEPROTO) db_forcehierarchicalanalysis(parent);
379
 
}
380
 
 
381
 
void cla_layconmodifyarcinst(ARCINST /*@unused@*/ *ai, INTBIG /*@unused@*/ oldx0,
382
 
        INTBIG /*@unused@*/ oldy0, INTBIG /*@unused@*/ oldx1,
383
 
        INTBIG /*@unused@*/ oldy1, INTBIG /*@unused@*/ oldwid, INTBIG /*@unused@*/ oldlen) {}
384
 
void cla_layconmodifyportproto(PORTPROTO /*@unused@*/ *pp, NODEINST /*@unused@*/ *oni,
385
 
        PORTPROTO /*@unused@*/ *opp) {}
386
 
void cla_layconmodifynodeproto(NODEPROTO /*@unused@*/ *np) {}
387
 
void cla_layconnewlib(LIBRARY /*@unused@*/ *lib) {}
388
 
void cla_layconkilllib(LIBRARY /*@unused@*/ *lib) {}
389
 
void cla_layconkillvariable(INTBIG /*@unused@*/ addr, INTBIG /*@unused@*/ type,
390
 
        INTBIG /*@unused@*/ key, INTBIG /*@unused@*/ saddr,
391
 
        INTBIG /*@unused@*/ stype, UINTBIG /*@unused@*/ *olddes) {}
392
 
void cla_layconinsertvariable(INTBIG /*@unused@*/ addr, INTBIG /*@unused@*/ type,
393
 
        INTBIG /*@unused@*/ key, INTBIG /*@unused@*/ aindex) {}
394
 
void cla_laycondeletevariable(INTBIG /*@unused@*/ addr, INTBIG /*@unused@*/ type,
395
 
        INTBIG /*@unused@*/ key, INTBIG /*@unused@*/ aindex, INTBIG /*@unused@*/ oldval) {}
396
 
void cla_layconsetvariable(void) {}
397
 
 
398
 
/******************** TEXT MODIFICATION CODE *************************/
399
 
 
400
 
/* #define TEXTPARTOFOBJECTBOUNDS 1 */
401
 
 
402
 
void cla_layconmodifyvariable(INTBIG addr, INTBIG type, INTBIG key, INTBIG stype,
403
 
        INTBIG aindex, INTBIG oldval)
404
 
{
405
 
#ifdef TEXTPARTOFOBJECTBOUNDS
406
 
        REGISTER char *name;
407
 
        REGISTER PORTPROTO *pp;
408
 
        REGISTER NODEINST *ni;
409
 
 
410
 
        /* look for modified text descriptor on exports */
411
 
        if (type == VPORTPROTO)
412
 
        {
413
 
                if ((stype&VCREF) != 0)
414
 
                {
415
 
                        name = changedvariablename(type, key, stype);
416
 
                        if (strcmp(name, "textdescript") == 0)
417
 
                        {
418
 
                                if (aindex == 1)
419
 
                                {
420
 
                                        pp = (PORTPROTO *)addr;
421
 
                                        ni = pp->subnodeinst;
422
 
                                        updategeom(ni->geom, ni->parent);
423
 
                                }
424
 
                        }
425
 
                }
426
 
        }
427
 
#endif
428
 
}
429
 
 
430
 
void cla_layconmodifydescript(INTBIG addr, INTBIG type, INTBIG key, UINTBIG *olddes)
431
 
{
432
 
#ifdef TEXTPARTOFOBJECTBOUNDS
433
 
        REGISTER NODEINST *ni;
434
 
        REGISTER ARCINST *ai;
435
 
        REGISTER PORTPROTO *pp;
436
 
 
437
 
        switch (type)
438
 
        {
439
 
                case VNODEINST:
440
 
                        ni = (NODEINST *)addr;
441
 
                        updategeom(ni->geom, ni->parent);
442
 
                        break;
443
 
                case VPORTPROTO:
444
 
                        pp = (PORTPROTO *)addr;
445
 
                        ni = pp->subnodeinst;
446
 
                        updategeom(ni->geom, ni->parent);
447
 
                        break;
448
 
                case VARCINST:
449
 
                        ai = (ARCINST *)addr;
450
 
                        updategeom(ai->geom, ai->parent);
451
 
                        break;
452
 
        }
453
 
#endif
454
 
}
455
 
 
456
 
/******************** NODE MODIFICATION CODE *************************/
457
 
 
458
 
/*
459
 
 * The meaning of cla_changeclock for object modification:
460
 
 *
461
 
 * ai->changed <  cla_changeclock-2  unmodified         arcs
462
 
 * ai->changed == cla_changeclock-2  unmodified rigid   arcs
463
 
 * ai->changed == cla_changeclock-1  unmodified unrigid arcs
464
 
 * ai->changed == cla_changeclock      modified rigid   arcs
465
 
 * ai->changed == cla_changeclock+1    modified unrigid arcs
466
 
 * ni->changed <  cla_changeclock-1  unmodified         nodes
467
 
 * ni->changed == cla_changeclock-1  size-changed       nodes
468
 
 * ni->changed == cla_changeclock    position-changed   nodes
469
 
 */
470
 
 
471
 
/*
472
 
 * routine to modify nodeinst "ni" by "deltalx" in low X, "deltaly" in low Y,
473
 
 * "deltahx" in high X, "deltahy" in high Y, and "dangle" tenth-degrees.  If
474
 
 * "announce" is true, report "start" and "end" changes on the node.
475
 
 * If the nodeinst is a portproto of the current facet and has any arcs
476
 
 * connected to it, the routine returns nonzero to indicate that the outer
477
 
 * facet has ports that moved (the nodeinst has exports).
478
 
 */
479
 
BOOLEAN cla_modifynodeinst(NODEINST *ni, INTBIG deltalx, INTBIG deltaly, INTBIG deltahx,
480
 
        INTBIG deltahy, INTBIG dangle, INTBIG dtrans, BOOLEAN announce)
481
 
{
482
 
        REGISTER INTBIG oldlx, oldly, oldhx, oldhy, change;
483
 
        REGISTER INTSML oldang, oldtrans;
484
 
 
485
 
        /* determine whether this is a position or size change */
486
 
        if (deltalx == deltahx && deltaly == deltahy)
487
 
        {
488
 
                if (deltalx == 0 && deltaly == 0 && dangle == 0 && dtrans == 0) change = -1; else
489
 
                        change = 0;
490
 
        } else change = -1;
491
 
 
492
 
        /* reject if this change has already been done */
493
 
        if (ni->changed >= cla_changeclock+change) return(FALSE);
494
 
 
495
 
        /* if simple rotation on transposed nodeinst, reverse rotation */
496
 
        if (ni->transpose != 0 && dtrans == 0) dangle = (3600 - dangle) % 3600;
497
 
 
498
 
        if (ni->changed < cla_changeclock-1 && announce)
499
 
                (void)db_change((INTBIG)ni, OBJECTSTART, VNODEINST, 0, 0, 0, 0, 0);
500
 
 
501
 
        /* make changes to the nodeinst */
502
 
        oldang = ni->rotation;     ni->rotation = (ni->rotation + dangle) % 3600;
503
 
        oldtrans = ni->transpose;  ni->transpose = (ni->transpose + dtrans) & 1;
504
 
        oldlx = ni->lowx;          ni->lowx += deltalx;
505
 
        oldhx = ni->highx;         ni->highx += deltahx;
506
 
        oldly = ni->lowy;          ni->lowy += deltaly;
507
 
        oldhy = ni->highy;         ni->highy += deltahy;
508
 
        updategeom(ni->geom, ni->parent);
509
 
 
510
 
#ifdef CLA_DEBUG
511
 
        if (cla_conlaydebug)
512
 
                ttyputmsg(M_("Change node %s by X(%s %s) Y(%s %s) r=%ld t=%ld"),
513
 
                        describenodeinst(ni), latoa(deltalx), latoa(deltahx), latoa(deltaly),
514
 
                                latoa(deltahy), dangle, dtrans);
515
 
#endif
516
 
 
517
 
        /* mark that this nodeinst has changed */
518
 
        if (ni->changed < cla_changeclock-1)
519
 
        {
520
 
                ni->changeaddr = (char *)db_change((INTBIG)ni, NODEINSTMOD, oldlx,
521
 
                        oldly, oldhx, oldhy, oldang, oldtrans);
522
 
                if (announce)
523
 
                        (void)db_change((INTBIG)ni, OBJECTEND, VNODEINST, 0, 0, 0, 0, 0);
524
 
        }
525
 
 
526
 
        ni->changed = cla_changeclock + change;
527
 
 
528
 
        /* see if this nodeinst is a port of the current facet */
529
 
        if (ni->firstportexpinst == NOPORTEXPINST) return(FALSE);
530
 
        return(TRUE);
531
 
}
532
 
 
533
 
/*
534
 
 * routine to modify all of the arcs connected to nodeinst "ni" (which has
535
 
 * been rotated by "dangle" tenth-degrees).  If the routine returns nonzero,
536
 
 * some ports on the current facet have moved and the facet must be
537
 
 * re-examined for portproto locations.
538
 
 */
539
 
BOOLEAN cla_modnodearcs(NODEINST *ni, INTBIG dangle, INTBIG dtrans)
540
 
{
541
 
        REGISTER BOOLEAN examinefacet;
542
 
 
543
 
        /* assume facet needs no further looks */
544
 
        examinefacet = FALSE;
545
 
 
546
 
        /* next look at arcs that run within this nodeinst */
547
 
        cla_modwithin(ni, dangle, dtrans);
548
 
 
549
 
        /* next look at the rest of the rigid arcs on this nodeinst */
550
 
        if (cla_modrigid(ni, dangle, dtrans)) examinefacet = TRUE;
551
 
 
552
 
        /* finally, look at rest of the flexible arcs on this nodeinst */
553
 
        if (cla_modflex(ni, dangle, dtrans)) examinefacet = TRUE;
554
 
 
555
 
        return(examinefacet);
556
 
}
557
 
 
558
 
/*
559
 
 * routine to modify the arcs that run within nodeinst "ni"
560
 
 */
561
 
void cla_modwithin(NODEINST *ni, INTBIG dangle, INTBIG dtrans)
562
 
{
563
 
        REGISTER PORTARCINST *pi;
564
 
        REGISTER ARCINST *ai;
565
 
        REGISTER INTBIG ox, oy, i, total;
566
 
        INTBIG nox, noy, onox, onoy;
567
 
        XARRAY trans;
568
 
 
569
 
        /* ignore all this stuff if the node just got created */
570
 
        if (((CHANGE *)ni->changeaddr)->changetype == NODEINSTNEW) return;
571
 
 
572
 
        /* build a list of arcs with both ends on this nodeinst */
573
 
        total = 0;
574
 
        for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
575
 
        {
576
 
                /* ignore if arcinst is not within the node */
577
 
                ai = pi->conarcinst;
578
 
                if (ai->end[0].nodeinst != ai->end[1].nodeinst) continue;
579
 
                if (ai->changed == cla_changeclock) continue;
580
 
                total++;
581
 
        }
582
 
        if (total == 0) return;
583
 
        if (total > cla_workingarccount)
584
 
        {
585
 
                if (cla_workingarccount > 0) efree((char *)cla_workingarcs);
586
 
                cla_workingarccount = 0;
587
 
                cla_workingarcs = (ARCINST **)emalloc(total * (sizeof (ARCINST *)), db_cluster);
588
 
                if (cla_workingarcs == 0) return;
589
 
                cla_workingarccount = total;
590
 
        }
591
 
        total = 0;
592
 
        for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
593
 
        {
594
 
                /* ignore if arcinst is not within the node */
595
 
                ai = pi->conarcinst;
596
 
                if (ai->end[0].nodeinst != ai->end[1].nodeinst) continue;
597
 
                if (ai->changed == cla_changeclock) continue;
598
 
                for(i=0; i<total; i++) if (cla_workingarcs[i] == ai) break;
599
 
                if (i >= total)
600
 
                        cla_workingarcs[total++] = ai;
601
 
        }
602
 
 
603
 
        /* look for arcs with both ends on this nodeinst */
604
 
        for(i=0; i<total; i++)
605
 
        {
606
 
                ai = cla_workingarcs[i];
607
 
                if ((ai->userbits&DEADA) != 0) continue;
608
 
 
609
 
                /* prepare transformation matrix */
610
 
                makeangle(dangle, dtrans, trans);
611
 
 
612
 
                /* compute old center of nodeinst */
613
 
                ox = (((CHANGE *)ni->changeaddr)->p1 + ((CHANGE *)ni->changeaddr)->p3) / 2;
614
 
                oy = (((CHANGE *)ni->changeaddr)->p2 + ((CHANGE *)ni->changeaddr)->p4) / 2;
615
 
 
616
 
                /* determine the new ends of the arcinst */
617
 
                cla_adjustmatrix(ni, ai->end[0].portarcinst->proto, trans);
618
 
                xform(ai->end[0].xpos-ox, ai->end[0].ypos-oy, &nox, &noy, trans);
619
 
                cla_adjustmatrix(ni, ai->end[1].portarcinst->proto, trans);
620
 
                xform(ai->end[1].xpos-ox, ai->end[1].ypos-oy, &onox, &onoy, trans);
621
 
#ifdef  CLA_DEBUG
622
 
                if (cla_conlaydebug)
623
 
                        ttyputmsg(M_("Internal arc %s moves 0:%s,%s  1:%s,%s"),
624
 
                                describearcinst(ai), latoa(nox), latoa(noy), latoa(onox), latoa(onoy));
625
 
#endif
626
 
                /* move the arcinst */
627
 
                cla_domovearcinst(ai, nox, noy, onox, onoy, 0);
628
 
        }
629
 
}
630
 
 
631
 
/*
632
 
 * routine to modify the rigid arcs that run from nodeinst "ni".  The nodeinst
633
 
 * has changed "dangle" tenth-degrees.  If any nodes that are ports in the
634
 
 * current facet change position, the routine returns nonzero to indicate
635
 
 * that instances of the current facet must be examined for arcinst motion.
636
 
 */
637
 
BOOLEAN cla_modrigid(NODEINST *ni, INTBIG dangle, INTBIG dtrans)
638
 
{
639
 
        REGISTER PORTPROTO *opt;
640
 
        REGISTER PORTARCINST *pi;
641
 
        REGISTER ARCINST *ai, **arclist;
642
 
        REGISTER NODEINST *ono;
643
 
        INTBIG ax[2], ay[2], onox, onoy, dx, dy;
644
 
        XARRAY trans;
645
 
        REGISTER INTBIG othx, othy, ox, oy, i, total, thisend, thatend;
646
 
        REGISTER INTBIG nextangle;
647
 
        REGISTER BOOLEAN examinefacet, locked;
648
 
 
649
 
        /* build a list of the rigid arcs on this nodeinst */
650
 
        total = 0;
651
 
        for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
652
 
        {
653
 
                /* ignore if arcinst is not rigid */
654
 
                ai = pi->conarcinst;
655
 
                if (ai->changed == cla_changeclock-1 || ai->changed == cla_changeclock+1) continue;
656
 
                if (ai->changed != cla_changeclock-2 && (ai->userbits&FIXED) == 0) continue;
657
 
                total++;
658
 
        }
659
 
        if (total == 0) return(FALSE);
660
 
        arclist = (ARCINST **)emalloc(total * (sizeof (ARCINST *)), el_tempcluster);
661
 
        if (arclist == 0) return(FALSE);
662
 
        i = 0;
663
 
        for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
664
 
        {
665
 
                /* ignore if arcinst is not rigid */
666
 
                ai = pi->conarcinst;
667
 
                if (ai->changed == cla_changeclock-1 || ai->changed == cla_changeclock+1) continue;
668
 
                if (ai->changed != cla_changeclock-2 && (ai->userbits&FIXED) == 0) continue;
669
 
                arclist[i++] = ai;
670
 
        }
671
 
 
672
 
        /* if simple rotation on transposed nodeinst, reverse rotation */
673
 
        nextangle = dangle;
674
 
        if (((CHANGE *)ni->changeaddr)->changetype != NODEINSTNEW &&
675
 
                ((CHANGE *)ni->changeaddr)->p6 != 0 && dtrans != 0)
676
 
                        nextangle = (3600 - dangle) % 3600;
677
 
 
678
 
        /* prepare transformation matrix and angle/transposition information */
679
 
        makeangle(nextangle, dtrans, trans);
680
 
 
681
 
        /* look for rigid arcs on this nodeinst */
682
 
        examinefacet = FALSE;
683
 
        for(i=0; i<total; i++)
684
 
        {
685
 
                ai = arclist[i];
686
 
                if ((ai->userbits&DEADA) != 0) continue;
687
 
                ai->userbits &= ~FIXEDMOD;
688
 
 
689
 
                /* if rigid arcinst has already been changed check its connectivity */
690
 
                if (ai->changed == cla_changeclock)
691
 
                {
692
 
                        cla_ensurearcinst(ai, 0);
693
 
                        continue;
694
 
                }
695
 
 
696
 
                /* find out which end of the arcinst is where, ignore internal arcs */
697
 
                thisend = thatend = 0;
698
 
                if (ai->end[0].nodeinst == ni) thatend++;
699
 
                if (ai->end[1].nodeinst == ni) thisend++;
700
 
                if (thisend == thatend) continue;
701
 
 
702
 
                if (((CHANGE *)ni->changeaddr)->changetype == NODEINSTNEW) ox = oy = 0; else
703
 
                {
704
 
                        ox = (((CHANGE *)ni->changeaddr)->p1 + ((CHANGE *)ni->changeaddr)->p3) / 2;
705
 
                        oy = (((CHANGE *)ni->changeaddr)->p2 + ((CHANGE *)ni->changeaddr)->p4) / 2;
706
 
                        cla_adjustmatrix(ni, ai->end[thisend].portarcinst->proto, trans);
707
 
                }
708
 
 
709
 
                /* figure out the new location of this arcinst connection */
710
 
                xform(ai->end[thisend].xpos-ox, ai->end[thisend].ypos-oy,
711
 
                        &ax[thisend], &ay[thisend], trans);
712
 
 
713
 
                ono = ai->end[thatend].nodeinst;
714
 
                opt = ai->end[thatend].portarcinst->proto;
715
 
#ifdef  CLA_DEBUG
716
 
                if (cla_conlaydebug)
717
 
                        ttyputmsg(M_("Modify rigid arc %s from %s to %s"),
718
 
                                describearcinst(ai), describenodeinst(ni), describenodeinst(ono));
719
 
#endif
720
 
 
721
 
                /* figure out the new location of that arcinst connection */
722
 
                xform(ai->end[thatend].xpos-ox, ai->end[thatend].ypos-oy, &ax[thatend],
723
 
                        &ay[thatend], trans);
724
 
#ifdef  CLA_DEBUG
725
 
                if (cla_conlaydebug)
726
 
                        ttyputmsg(M_("Other end of arc moves to (%s,%s)"),
727
 
                                latoa(ax[thatend]), latoa(ay[thatend]));
728
 
#endif
729
 
 
730
 
                /* see if other nodeinst has changed */
731
 
                locked = FALSE;
732
 
                if (ono->changed == cla_changeclock) locked = TRUE;
733
 
                if (ono->proto->primindex == 0)
734
 
                {
735
 
                        if ((ono->parent->userbits&NILOCKED) != 0) locked = TRUE;
736
 
                } else
737
 
                {
738
 
                        if ((us_useroptions&NOPRIMCHANGES) != 0 &&
739
 
                                (ono->proto->userbits&LOCKEDPRIM) != 0) locked = TRUE;
740
 
                }
741
 
                if (!locked)
742
 
                {
743
 
                        /* compute port motion within the other nodeinst (is this right? !!!) */
744
 
                        cla_oldportposition(ono, opt, &onox, &onoy);
745
 
                        portposition(ono, opt, &dx, &dy);
746
 
                        othx = dx - onox;   othy = dy - onoy;
747
 
 
748
 
                        /* figure out the new location of the other nodeinst */
749
 
                        onox = (ono->lowx + ono->highx) / 2;
750
 
                        onoy = (ono->lowy + ono->highy) / 2;
751
 
                        xform(onox-ox, onoy-oy, &dx, &dy, trans);
752
 
                        dx = dx - onox - othx;
753
 
                        dy = dy - onoy - othy;
754
 
 
755
 
                        /* move the other nodeinst */
756
 
                        nextangle = dangle;
757
 
                        if (dtrans != 0 && ono->transpose != ((CHANGE *)ni->changeaddr)->p6)
758
 
                                nextangle = (3600 - nextangle) % 3600;
759
 
 
760
 
                        /* ignore null motion on nodes that have already been examined */
761
 
                        if (dx != 0 || dy != 0 || nextangle != 0 || dtrans != 0 || ono->changed != cla_changeclock-1)
762
 
                        {
763
 
                                ai->userbits |= FIXEDMOD;
764
 
                                if (cla_modifynodeinst(ono, dx, dy, dx, dy, nextangle, dtrans, TRUE))
765
 
                                        examinefacet = TRUE;
766
 
                        }
767
 
                }
768
 
 
769
 
                /* move the arcinst */
770
 
#ifdef  CLA_DEBUG
771
 
                if (cla_conlaydebug)
772
 
                        ttyputmsg(M_("Now arc runs from (%s,%s) to (%s,%s)"),
773
 
                                latoa(ax[0]), latoa(ay[0]), latoa(ax[1]), latoa(ay[1]));
774
 
#endif
775
 
                cla_domovearcinst(ai, ax[0],ay[0], ax[1],ay[1], 0);
776
 
        }
777
 
 
778
 
        /* re-scan rigid arcs and recursively modify arcs on other nodes */
779
 
        for(i=0; i<total; i++)
780
 
        {
781
 
                ai = arclist[i];
782
 
                if ((ai->userbits&DEADA) != 0) continue;
783
 
 
784
 
                /* only want arcinst that was just explored */
785
 
                if ((ai->userbits & FIXEDMOD) == 0) continue;
786
 
 
787
 
                /* get the other nodeinst */
788
 
                if (ai->end[0].nodeinst == ni) ono = ai->end[1].nodeinst; else
789
 
                        ono = ai->end[0].nodeinst;
790
 
 
791
 
                nextangle = dangle;
792
 
                if (dtrans != 0 && ((CHANGE *)ono->changeaddr)->p6 != ((CHANGE *)ni->changeaddr)->p6)
793
 
                        nextangle = (3600 - nextangle) % 3600;
794
 
                if (cla_modnodearcs(ono, nextangle, dtrans)) examinefacet = TRUE;
795
 
        }
796
 
        efree((char *)arclist);
797
 
        return(examinefacet);
798
 
}
799
 
 
800
 
/*
801
 
 * routine to modify the flexible arcs connected to nodeinst "ni".  If any
802
 
 * nodes that are ports move, the routine returns nonzero to indicate that
803
 
 * instances of the current facet must be examined for arcinst motion
804
 
 */
805
 
BOOLEAN cla_modflex(NODEINST *ni, INTBIG dangle, INTBIG dtrans)
806
 
{
807
 
        REGISTER PORTARCINST *pi;
808
 
        REGISTER ARCINST *ai, **arclist;
809
 
        REGISTER NODEINST *ono;
810
 
        REGISTER INTBIG i, total, ox, oy, odx, ody, thisend, thatend, mangle;
811
 
        REGISTER INTBIG nextangle;
812
 
        REGISTER BOOLEAN examinefacet;
813
 
        XARRAY trans;
814
 
        INTBIG ax[2], ay[2], dx, dy, lx, hx, ly, hy;
815
 
        static POLYGON *poly = NOPOLYGON;
816
 
 
817
 
        /* build a list of the flexible arcs on this nodeinst */
818
 
        total = 0;
819
 
        for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
820
 
        {
821
 
                /* ignore if arcinst is not flexible */
822
 
                ai = pi->conarcinst;
823
 
                if (ai->changed == cla_changeclock-2 || ai->changed == cla_changeclock) continue;
824
 
                if (ai->changed != cla_changeclock-1 && (ai->userbits&FIXED) != 0) continue;
825
 
                total++;
826
 
        }
827
 
        if (total == 0) return(FALSE);
828
 
        arclist = (ARCINST **)emalloc(total * (sizeof (ARCINST *)), el_tempcluster);
829
 
        if (arclist == 0) return(FALSE);
830
 
        i = 0;
831
 
        for(pi = ni->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
832
 
        {
833
 
                /* ignore if arcinst is not flexible */
834
 
                ai = pi->conarcinst;
835
 
                if (ai->changed == cla_changeclock-2 || ai->changed == cla_changeclock) continue;
836
 
                if (ai->changed != cla_changeclock-1 && (ai->userbits&FIXED) != 0) continue;
837
 
                arclist[i++] = ai;
838
 
        }
839
 
 
840
 
        /* if simple rotation on transposed nodeinst, reverse rotation */
841
 
        nextangle = dangle;
842
 
        if (((CHANGE *)ni->changeaddr)->changetype != NODEINSTNEW &&
843
 
                ((CHANGE *)ni->changeaddr)->p6 != 0 && dtrans != 0)
844
 
                        nextangle = (3600 - dangle) % 3600;
845
 
 
846
 
        /* prepare transformation matrix and angle/transposition information */
847
 
        makeangle(nextangle, dtrans, trans);
848
 
 
849
 
        /* look at all of the flexible arcs on this nodeinst */
850
 
        examinefacet = FALSE;
851
 
        for(i=0; i<total; i++)
852
 
        {
853
 
                ai = arclist[i];
854
 
                if ((ai->userbits&DEADA) != 0) continue;
855
 
 
856
 
                /* if flexible arcinst has been changed, verify its connectivity */
857
 
#ifdef  CLA_DEBUG
858
 
                if (cla_conlaydebug)
859
 
                {
860
 
                        ttyputmsg(M_("Considering arc %s (clock=%ld, curclock=%ld)"),
861
 
                                describearcinst(ai), ai->changed, cla_changeclock+1);
862
 
                }
863
 
#endif
864
 
                if (ai->changed >= cla_changeclock+1)
865
 
                {
866
 
                        cla_ensurearcinst(ai, 1);
867
 
                        continue;
868
 
                }
869
 
 
870
 
                /* figure where each end of the arcinst is, ignore internal arcs */
871
 
                thisend = thatend = 0;
872
 
                if (ai->end[0].nodeinst == ni) thatend++;
873
 
                if (ai->end[1].nodeinst == ni) thisend++;
874
 
                if (thisend == thatend) continue;
875
 
 
876
 
                /* if nodeinst motion stays within port area, ignore the arcinst */
877
 
                if ((ai->userbits&CANTSLIDE) == 0 &&
878
 
                        db_stillinport(ai, thisend, ai->end[thisend].xpos, ai->end[thisend].ypos))
879
 
                                continue;
880
 
 
881
 
                if (((CHANGE *)ni->changeaddr)->changetype == NODEINSTNEW) ox = oy = 0; else
882
 
                {
883
 
                        ox = (((CHANGE *)ni->changeaddr)->p1 + ((CHANGE *)ni->changeaddr)->p3) / 2;
884
 
                        oy = (((CHANGE *)ni->changeaddr)->p2 + ((CHANGE *)ni->changeaddr)->p4) / 2;
885
 
                        cla_adjustmatrix(ni, ai->end[thisend].portarcinst->proto, trans);
886
 
                }
887
 
 
888
 
                /* figure out the new location of this arcinst connection */
889
 
                xform(ai->end[thisend].xpos-ox, ai->end[thisend].ypos-oy,
890
 
                        &ax[thisend], &ay[thisend], trans);
891
 
 
892
 
                /* make sure the arc end is still in the port */
893
 
                if (poly == NOPOLYGON) poly = allocstaticpolygon(4, db_cluster);
894
 
                shapeportpoly(ai->end[thisend].nodeinst, ai->end[thisend].portarcinst->proto,
895
 
                        poly, FALSE);
896
 
                if (!isinside(ax[thisend], ay[thisend], poly))
897
 
                {
898
 
                        getbbox(poly, &lx, &hx, &ly, &hy);
899
 
                        if (ay[thisend] >= ly && ay[thisend] <= hy)
900
 
                        {
901
 
                                /* extend arc horizontally to fit in port */
902
 
                                if (ax[thisend] < lx) ax[thisend] = lx; else
903
 
                                        if (ax[thisend] > hx) ax[thisend] = hx;
904
 
                        } else if (ax[thisend] >= lx && ax[thisend] <= hx)
905
 
                        {
906
 
                                /* extend arc vertically to fit in port */
907
 
                                if (ay[thisend] < ly) ay[thisend] = ly; else
908
 
                                        if (ay[thisend] > hy) ay[thisend] = hy;
909
 
                        } else
910
 
                        {
911
 
                                /* extend arc arbitrarily to fit in port */
912
 
                                closestpoint(poly, &ax[thisend], &ay[thisend]);
913
 
                        }
914
 
                }
915
 
 
916
 
                /* get other end of arcinst and its position */
917
 
                ono = ai->end[thatend].nodeinst;
918
 
                ax[thatend] = ai->end[thatend].xpos;
919
 
                ay[thatend] = ai->end[thatend].ypos;
920
 
#ifdef  CLA_DEBUG
921
 
                if (cla_conlaydebug)
922
 
                {
923
 
                        ttyputmsg(M_("Modify flexible arc %s from %s to %s"),
924
 
                                describearcinst(ai), describenodeinst(ni), describenodeinst(ono));
925
 
                }
926
 
#endif
927
 
 
928
 
                /* see if other nodeinst has changed */
929
 
                mangle = 1;
930
 
                if ((ai->userbits&FIXANG) == 0) mangle = 0;
931
 
                if (ono->proto->primindex == 0)
932
 
                {
933
 
                        if ((ono->parent->userbits&NILOCKED) != 0) mangle = 0;
934
 
                } else
935
 
                {
936
 
                        if ((us_useroptions&NOPRIMCHANGES) != 0 &&
937
 
                                (ono->proto->userbits&LOCKEDPRIM) != 0) mangle = 0;
938
 
                }
939
 
                if (mangle != 0)
940
 
                {
941
 
                        /* other nodeinst untouched, mangle it */
942
 
                        dx = ax[thisend] - ai->end[thisend].xpos;
943
 
                        dy = ay[thisend] - ai->end[thisend].ypos;
944
 
                        odx = ax[thatend] - ai->end[thatend].xpos;
945
 
                        ody = ay[thatend] - ai->end[thatend].ypos;
946
 
                        if (ai->end[thisend].xpos == ai->end[thatend].xpos)
947
 
                        {
948
 
                                /* null arcinst must not be explicitly horizontal */
949
 
                                if (ai->end[thisend].ypos != ai->end[thatend].ypos ||
950
 
                                        ((ai->userbits&AANGLE) >> AANGLESH) == 90 ||
951
 
                                                ((ai->userbits&AANGLE) >> AANGLESH) == 270)
952
 
                                {
953
 
                                        /* vertical arcinst: see if it really moved in X */
954
 
                                        if (dx == odx) dx = odx = 0;
955
 
 
956
 
                                        /* move horizontal, shrink vertical */
957
 
                                        ax[thatend] += dx-odx;
958
 
 
959
 
                                        /* see if next nodeinst need not be moved */
960
 
                                        if (dx != odx && (ai->userbits&CANTSLIDE) == 0 &&
961
 
                                                db_stillinport(ai, thatend, ax[thatend], ay[thatend]))
962
 
                                                        dx = odx = 0;
963
 
 
964
 
                                        /* if other node already moved, don't move it any more */
965
 
                                        if (ono->changed >= cla_changeclock) dx = odx = 0;
966
 
 
967
 
#ifdef  CLA_DEBUG
968
 
                                        if (cla_conlaydebug)
969
 
                                                ttyputmsg(M_("  Moving other end of arc to (%s,%s), other node by (%s,0)"),
970
 
                                                        latoa(ax[thatend]), latoa(ay[thatend]), latoa(dx-odx));
971
 
#endif
972
 
                                        if (dx != odx)
973
 
                                        {
974
 
                                                if (cla_modifynodeinst(ono, dx-odx, 0, dx-odx, 0, 0, 0, TRUE))
975
 
                                                        examinefacet = TRUE;
976
 
                                        }
977
 
                                        cla_domovearcinst(ai, ax[0],ay[0], ax[1],ay[1], 1);
978
 
                                        if (dx != odx)
979
 
                                                if (cla_modnodearcs(ono, 0, 0)) examinefacet = TRUE;
980
 
                                        continue;
981
 
                                }
982
 
                        }
983
 
                        if (ai->end[thisend].ypos == ai->end[thatend].ypos)
984
 
                        {
985
 
                                /* horizontal arcinst: see if it really moved in Y */
986
 
                                if (dy == ody) dy = ody = 0;
987
 
 
988
 
                                /* shrink horizontal, move vertical */
989
 
                                ay[thatend] += dy-ody;
990
 
 
991
 
                                /* see if next nodeinst need not be moved */
992
 
                                if (dy != ody && (ai->userbits&CANTSLIDE) == 0 &&
993
 
                                        db_stillinport(ai, thatend, ax[thatend], ay[thatend]))
994
 
                                                dy = ody = 0;
995
 
 
996
 
                                /* if other node already moved, don't move it any more */
997
 
                                if (ono->changed >= cla_changeclock) dx = odx = 0;
998
 
 
999
 
#ifdef  CLA_DEBUG
1000
 
                                if (cla_conlaydebug)
1001
 
                                        ttyputmsg(M_("  Moving other end of arc to (%s,%s), other node by (0,%s)"),
1002
 
                                                latoa(ax[thatend]), latoa(ay[thatend]), latoa(dy-ody));
1003
 
#endif
1004
 
                                if (dy != ody)
1005
 
                                {
1006
 
                                        if (cla_modifynodeinst(ono, 0, dy-ody, 0, dy-ody, 0, 0, TRUE))
1007
 
                                                examinefacet = TRUE;
1008
 
                                }
1009
 
                                cla_domovearcinst(ai, ax[0],ay[0], ax[1],ay[1], 1);
1010
 
                                if (dy != ody) if (cla_modnodearcs(ono, 0, 0)) examinefacet = TRUE;
1011
 
                                continue;
1012
 
                        }
1013
 
 
1014
 
                        /***** THIS CODE HANDLES ALL-ANGLE RIGIDITY WITH THE FIXED-ANGLE CONSTRAINT *****/
1015
 
 
1016
 
                        /* special code to handle nonorthogonal fixed-angles */
1017
 
                        cla_nonorthogfixang(ai, thisend, thatend, ono, ax, ay);
1018
 
                        dx = ax[thatend] - ai->end[thatend].xpos;
1019
 
                        dy = ay[thatend] - ai->end[thatend].ypos;
1020
 
 
1021
 
                        /* change the arc */
1022
 
                        cla_updatearc(ai, ax[0],ay[0], ax[1],ay[1], 1);
1023
 
 
1024
 
                        /* if other node already moved, don't move it any more */
1025
 
                        if (ono->changed >= cla_changeclock) dx = dy = 0;
1026
 
 
1027
 
                        if (dx != 0 || dy != 0)
1028
 
                        {
1029
 
                                if (cla_modifynodeinst(ono, dx, dy, dx, dy, 0, 0, TRUE))
1030
 
                                        examinefacet = TRUE;
1031
 
                                if (cla_modnodearcs(ono, 0, 0)) examinefacet = TRUE;
1032
 
                        }
1033
 
                        continue;
1034
 
                }
1035
 
 
1036
 
                /* other node has changed or arc is funny, just use its position */
1037
 
#ifdef  CLA_DEBUG
1038
 
                if (cla_conlaydebug)
1039
 
                        ttyputmsg(M_("  ! Moving arc %s to (%s,%s)-(%s,%s)"), describearcinst(ai),
1040
 
                                latoa(ax[0]), latoa(ay[0]), latoa(ax[1]), latoa(ay[1]));
1041
 
#endif
1042
 
                cla_domovearcinst(ai, ax[0],ay[0], ax[1],ay[1], 1);
1043
 
        }
1044
 
        efree((char *)arclist);
1045
 
        return(examinefacet);
1046
 
}
1047
 
 
1048
 
/*
1049
 
 * routine to determine the motion of a nonorthogonal arcinst "ai" given that
1050
 
 * its "thisend" end has moved to (ax[thisend],ay[thisend]) and its other end must be
1051
 
 * determined in (ax[thatend],ay[thatend]).  The node on the other end is "ono".
1052
 
 */
1053
 
void cla_nonorthogfixang(ARCINST *ai, INTBIG thisend, INTBIG thatend, NODEINST *ono,
1054
 
        INTBIG ax[2], INTBIG ay[2])
1055
 
{
1056
 
        REGISTER PORTARCINST *pi;
1057
 
        REGISTER ARCINST *oai, *bestai;
1058
 
        REGISTER INTBIG bestdist;
1059
 
        INTBIG ix, iy;
1060
 
 
1061
 
        /* look for longest other arc on "ono" to determine proper end position */
1062
 
        bestdist = -1;
1063
 
        for(pi = ono->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
1064
 
        {
1065
 
                oai = pi->conarcinst;
1066
 
                if (oai == ai) continue;
1067
 
                if (oai->length < bestdist) continue;
1068
 
                bestdist = oai->length;
1069
 
                bestai = oai;
1070
 
        }
1071
 
 
1072
 
        /* if no other arcs, allow that end to move the same as this end */
1073
 
        if (bestdist < 0)
1074
 
        {
1075
 
                ax[thatend] += ax[thisend] - ai->end[thisend].xpos;
1076
 
                ay[thatend] += ay[thisend] - ai->end[thisend].ypos;
1077
 
                return;
1078
 
        }
1079
 
 
1080
 
        /* compute intersection of arc "bestai" with new moved arc "ai" */
1081
 
        if (intersect(ax[thisend],ay[thisend], ((ai->userbits&AANGLE) >> AANGLESH) * 10,
1082
 
                bestai->end[0].xpos, bestai->end[0].ypos,
1083
 
                        ((bestai->userbits&AANGLE) >> AANGLESH) * 10, &ix, &iy) < 0)
1084
 
        {
1085
 
                ax[thatend] += ax[thisend] - ai->end[thisend].xpos;
1086
 
                ay[thatend] += ay[thisend] - ai->end[thisend].ypos;
1087
 
                return;
1088
 
        }
1089
 
        ax[thatend] = ix;
1090
 
        ay[thatend] = iy;
1091
 
}
1092
 
 
1093
 
/*
1094
 
 * routine to ensure that arcinst "ai" is still connected properly at each
1095
 
 * end.  If it is not, it must be jogged or adjusted.  The nature of the
1096
 
 * arcinst is in "arctyp" (0 for rigid, 1 for flexible)
1097
 
 */
1098
 
void cla_ensurearcinst(ARCINST *ai, INTBIG arctyp)
1099
 
{
1100
 
        REGISTER BOOLEAN inside0, inside1;
1101
 
        INTBIG lx0, lx1, hx0, hx1, ly0, ly1, hy0, hy1, fx, fy, tx, ty;
1102
 
        static POLYGON *poly0 = NOPOLYGON, *poly1 = NOPOLYGON;
1103
 
 
1104
 
        /* if nothing is outside port, quit */
1105
 
        inside0 = db_stillinport(ai, 0, ai->end[0].xpos, ai->end[0].ypos);
1106
 
        inside1 = db_stillinport(ai, 1, ai->end[1].xpos, ai->end[1].ypos);
1107
 
        if (inside0 && inside1) return;
1108
 
 
1109
 
        /* make sure there is a polygon */
1110
 
        if (poly0 == NOPOLYGON) poly0 = allocstaticpolygon(4, cla_constraint->cluster);
1111
 
        if (poly1 == NOPOLYGON) poly1 = allocstaticpolygon(4, cla_constraint->cluster);
1112
 
 
1113
 
        /* get area of the ports */
1114
 
        shapeportpoly(ai->end[0].nodeinst, ai->end[0].portarcinst->proto, poly0, FALSE);
1115
 
        shapeportpoly(ai->end[1].nodeinst, ai->end[1].portarcinst->proto, poly1, FALSE);
1116
 
 
1117
 
        /* if arcinst is not fixed-angle, run it directly to the port centers */
1118
 
        if ((ai->userbits&FIXANG) == 0)
1119
 
        {
1120
 
                getcenter(poly0, &fx, &fy);
1121
 
                getcenter(poly1, &tx, &ty);
1122
 
#ifdef  CLA_DEBUG
1123
 
                if (cla_conlaydebug)
1124
 
                        ttyputmsg(M_("Ensuring rigid arc %s"), describearcinst(ai));
1125
 
#endif
1126
 
                cla_domovearcinst(ai, fx, fy, tx, ty, arctyp);
1127
 
                return;
1128
 
        }
1129
 
 
1130
 
        /* get bounding boxes of polygons */
1131
 
        getbbox(poly0, &lx0, &hx0, &ly0, &hy0);
1132
 
        getbbox(poly1, &lx1, &hx1, &ly1, &hy1);
1133
 
 
1134
 
        /* if manhattan path runs between the ports, adjust the arcinst */
1135
 
        if (lx0 <= hx1 && lx1 <= hx0)
1136
 
        {
1137
 
                /* arcinst runs vertically */
1138
 
                tx = fx = (maxi(lx0,lx1) + mini(hx0,hx1)) / 2;
1139
 
                fy = (ly0+hy0) / 2;   ty = (ly1+hy1) / 2;
1140
 
                closestpoint(poly0, &fx, &fy);
1141
 
                closestpoint(poly1, &tx, &ty);
1142
 
#ifdef  CLA_DEBUG
1143
 
                if (cla_conlaydebug)
1144
 
                        ttyputmsg(M_("Ensuring manhattan arc %s"), describearcinst(ai));
1145
 
#endif
1146
 
                cla_domovearcinst(ai, fx, fy, tx, ty, arctyp);
1147
 
                return;
1148
 
        }
1149
 
        if (ly0 <= hy1 && ly1 <= hy0)
1150
 
        {
1151
 
                /* arcinst runs horizontally */
1152
 
                ty = fy = (maxi(ly0,ly1) + mini(hy0,hy1)) / 2;
1153
 
                fx = (lx0+hx0) / 2;   tx = (lx1+hx1) / 2;
1154
 
                closestpoint(poly0, &fx, &fy);
1155
 
                closestpoint(poly1, &tx, &ty);
1156
 
#ifdef  CLA_DEBUG
1157
 
                if (cla_conlaydebug)
1158
 
                        ttyputmsg(M_("Ensuring manhattan arc %s"), describearcinst(ai));
1159
 
#endif
1160
 
                cla_domovearcinst(ai, fx, fy, tx, ty, arctyp);
1161
 
                return;
1162
 
        }
1163
 
 
1164
 
        /* give up and jog the arcinst */
1165
 
        getcenter(poly0, &fx, &fy);
1166
 
        getcenter(poly1, &tx, &ty);
1167
 
        cla_domovearcinst(ai, fx, fy, tx, ty, arctyp);
1168
 
}
1169
 
 
1170
 
/*
1171
 
 * routine to update arc "ai" so that its ends run from (fx,fy) to (tx,ty).
1172
 
 * The type of the arc is in "arctyp" for marking the change.
1173
 
 */
1174
 
void cla_updatearc(ARCINST *ai, INTBIG fx, INTBIG fy, INTBIG tx, INTBIG ty, INTBIG arctyp)
1175
 
{
1176
 
        REGISTER INTBIG oldxA, oldyA, oldxB, oldyB, oldlen;
1177
 
 
1178
 
        (void)db_change((INTBIG)ai, OBJECTSTART, VARCINST, 0, 0, 0, 0, 0);
1179
 
 
1180
 
        /* save old arc state */
1181
 
        oldxA = ai->end[0].xpos;   oldyA = ai->end[0].ypos;
1182
 
        oldxB = ai->end[1].xpos;   oldyB = ai->end[1].ypos;
1183
 
        oldlen = ai->length;
1184
 
 
1185
 
        /* set the proper arcinst position */
1186
 
#ifdef CLA_DEBUG
1187
 
        if (cla_conlaydebug)
1188
 
                ttyputmsg(M_("Change arc %s from (%s,%s)-(%s,%s) to (%s,%s)-(%s,%s)"),
1189
 
                        describearcinst(ai), latoa(ai->end[0].xpos), latoa(ai->end[0].ypos),
1190
 
                                latoa(ai->end[1].xpos), latoa(ai->end[1].ypos),
1191
 
                                        latoa(fx), latoa(fy), latoa(tx), latoa(ty));
1192
 
#endif
1193
 
        ai->end[0].xpos = fx;
1194
 
        ai->end[0].ypos = fy;
1195
 
        ai->end[1].xpos = tx;
1196
 
        ai->end[1].ypos = ty;
1197
 
        ai->length = computedistance(fx,fy, tx,ty);
1198
 
        determineangle(ai);
1199
 
        (void)setshrinkvalue(ai, TRUE);
1200
 
        updategeom(ai->geom, ai->parent);
1201
 
 
1202
 
        /* see if the arc has changed before */
1203
 
        if (((CHANGE *)ai->changeaddr) == NOCHANGE)
1204
 
        {
1205
 
                /* announce new arcinst change */
1206
 
                ai->changeaddr = (char *)db_change((INTBIG)ai, ARCINSTMOD, oldxA,
1207
 
                        oldyA, oldxB, oldyB, ai->width, oldlen);
1208
 
                ai->changed = cla_changeclock + arctyp;
1209
 
        }
1210
 
        (void)db_change((INTBIG)ai, OBJECTEND, VARCINST, 0, 0, 0, 0, 0);
1211
 
}
1212
 
 
1213
 
void cla_domovearcinst(ARCINST *ai, INTBIG fx, INTBIG fy, INTBIG tx, INTBIG ty, INTBIG arctyp)
1214
 
{
1215
 
        REGISTER NODEPROTO *np, *pnt;
1216
 
        REGISTER ARCPROTO *ap;
1217
 
        REGISTER ARCINST *ar1, *ar2, *ar3;
1218
 
        REGISTER PORTPROTO *pp, *fpt, *tpt;
1219
 
        REGISTER NODEINST *no1, *no2, *fno, *tno;
1220
 
        REGISTER INTBIG oldxA, oldyA, oldxB, oldyB, wid, oldbits, lx, hx, ly, hy;
1221
 
        INTBIG psx, psy;
1222
 
 
1223
 
        /* check for null arcinst motion */
1224
 
        if (fx == ai->end[0].xpos && fy == ai->end[0].ypos &&
1225
 
                tx == ai->end[1].xpos && ty == ai->end[1].ypos)
1226
 
        {
1227
 
                /* only ignore null motion on fixed-angle requests */
1228
 
                if (arctyp != 0) return;
1229
 
        }
1230
 
 
1231
 
        /* if the angle is the same or doesn't need to be, simply make the change */
1232
 
        if ((ai->userbits&FIXANG) == 0 ||
1233
 
                ((ai->userbits&FIXED) != 0 && ai->changed != cla_changeclock-1) ||
1234
 
                ai->changed == cla_changeclock-2 ||
1235
 
                (fx == tx && fy == ty) ||
1236
 
                ((((INTBIG)ai->userbits&AANGLE) >> AANGLESH)*10)%1800 == figureangle(fx, fy, tx, ty)%1800)
1237
 
        {
1238
 
                cla_updatearc(ai, fx, fy, tx, ty, arctyp);
1239
 
                return;
1240
 
        }
1241
 
#ifdef  CLA_DEBUG
1242
 
        if (cla_conlaydebug)
1243
 
        {
1244
 
                ttyputmsg(M_("Jogging arc %s (0%o) to run from (%s,%s) to (%s,%s)"),
1245
 
                        describearcinst(ai), ai, latoa(fx), latoa(fy), latoa(tx), latoa(ty));
1246
 
        }
1247
 
#endif
1248
 
 
1249
 
        /* manhattan arcinst becomes nonmanhattan: remember facts about it */
1250
 
        fno = ai->end[0].nodeinst;   fpt = ai->end[0].portarcinst->proto;
1251
 
        tno = ai->end[1].nodeinst;   tpt = ai->end[1].portarcinst->proto;
1252
 
        ap = ai->proto;   pnt = ai->parent;   wid = ai->width;
1253
 
        oldbits = ai->userbits;
1254
 
 
1255
 
        /* figure out what nodeinst proto connects these arcs */
1256
 
        np = getpinproto(ap);
1257
 
        defaultnodesize(np, &psx, &psy);
1258
 
 
1259
 
        /* replace it with three arcs and two nodes */
1260
 
        if (ai->end[0].xpos == ai->end[1].xpos)
1261
 
        {
1262
 
                /* arcinst was vertical */
1263
 
                oldyA = oldyB = (ty+fy) / 2;
1264
 
                oldxA = fx;   oldxB = tx;
1265
 
                lx = oldxB - psx/2; hx = lx + psx;
1266
 
                ly = oldyB - psy/2; hy = ly + psy;
1267
 
                no1 = db_newnodeinst(np, lx, hx, ly, hy, 0, 0, pnt);
1268
 
                lx = oldxA - psx/2; hx = lx + psx;
1269
 
                ly = oldyA - psy/2; hy = ly + psy;
1270
 
                no2 = db_newnodeinst(np, lx, hx, ly, hy, 0, 0, pnt);
1271
 
        } else
1272
 
        {
1273
 
                /* assume horizontal arcinst */
1274
 
                oldyA = fy;   oldyB = ty;
1275
 
                oldxA = oldxB = (tx+fx) / 2;
1276
 
                lx = oldxB - psx/2; hx = lx + psx;
1277
 
                ly = oldyB - psy/2; hy = ly + psy;
1278
 
                no1 = db_newnodeinst(np, lx, hx, ly, hy, 0, 0, pnt);
1279
 
                lx = oldxA - psx/2; hx = lx + psx;
1280
 
                ly = oldyA - psy/2; hy = ly + psy;
1281
 
                no2 = db_newnodeinst(np, lx, hx, ly, hy, 0, 0, pnt);
1282
 
        }
1283
 
        if (no1 == NONODEINST || no2 == NONODEINST)
1284
 
        {
1285
 
                ttyputerr(_("Problem creating jog pins"));
1286
 
                return;
1287
 
        }
1288
 
        (void)db_change((INTBIG)no1, OBJECTEND, VNODEINST, 0, 0, 0, 0, 0);
1289
 
        (void)db_change((INTBIG)no2, OBJECTEND, VNODEINST, 0, 0, 0, 0, 0);
1290
 
        pp = np->firstportproto;
1291
 
        ar1 = db_newarcinst(ap, wid, oldbits, fno, fpt, fx,fy, no2, pp, oldxA,oldyA, pnt);
1292
 
        if ((oldbits&ISNEGATED) != 0) oldbits &= ~ISNEGATED;
1293
 
        ar2 = db_newarcinst(ap, wid, oldbits, no2, pp, oldxA,oldyA, no1, pp, oldxB,oldyB, pnt);
1294
 
        ar3 = db_newarcinst(ap, wid, oldbits, no1, pp, oldxB,oldyB, tno, tpt, tx,ty, pnt);
1295
 
        if (ar1 == NOARCINST || ar2 == NOARCINST || ar3 == NOARCINST)
1296
 
        {
1297
 
                ttyputerr(_("Problem creating jog arcs"));
1298
 
                return;
1299
 
        }
1300
 
        (void)copyvars((INTBIG)ai, VARCINST, (INTBIG)ar2, VARCINST);
1301
 
        (void)db_change((INTBIG)ar1, OBJECTEND, VARCINST, 0, 0, 0, 0, 0);
1302
 
        (void)db_change((INTBIG)ar2, OBJECTEND, VARCINST, 0, 0, 0, 0, 0);
1303
 
        (void)db_change((INTBIG)ar3, OBJECTEND, VARCINST, 0, 0, 0, 0, 0);
1304
 
        ar1->changed = cla_changeclock + arctyp;
1305
 
        ar2->changed = cla_changeclock + arctyp;
1306
 
        ar3->changed = cla_changeclock + arctyp;
1307
 
 
1308
 
        /* now kill the arcinst */
1309
 
        (void)db_change((INTBIG)ai, OBJECTSTART, VARCINST, 0, 0, 0, 0, 0);
1310
 
        if ((CHANGE *)ai->changeaddr != NOCHANGE)
1311
 
        {
1312
 
                ai->end[0].xpos = ((CHANGE *)ai->changeaddr)->p1;
1313
 
                ai->end[0].ypos = ((CHANGE *)ai->changeaddr)->p2;
1314
 
                ai->end[1].xpos = ((CHANGE *)ai->changeaddr)->p3;
1315
 
                ai->end[1].ypos = ((CHANGE *)ai->changeaddr)->p4;
1316
 
                ai->length = computedistance(ai->end[0].xpos, ai->end[0].ypos,
1317
 
                        ai->end[1].xpos, ai->end[1].ypos);
1318
 
                ai->width = ((CHANGE *)ai->changeaddr)->p5;
1319
 
                determineangle(ai);
1320
 
        }
1321
 
        db_killarcinst(ai);
1322
 
}
1323
 
 
1324
 
/*
1325
 
 * routine to adjust the transformation matrix "trans" by placing translation
1326
 
 * information for nodeinst "ni", port "pp".
1327
 
 *
1328
 
 * there are only two types of nodeinst changes: internal and external.
1329
 
 * The internal changes are scaling and port motion changes that
1330
 
 * are usually caused by other changes within the facet.  The external
1331
 
 * changes are rotation and transposition.  These two changes never
1332
 
 * occur at the same time.  There is also translation change that
1333
 
 * can occur at any time and is of no importance here.  What is
1334
 
 * important is that the transformation matrix "trans" handles
1335
 
 * the external changes and internal changes.  External changes are already
1336
 
 * set by the "makeangle" subroutine and internal changes are
1337
 
 * built into the matrix here.
1338
 
 */
1339
 
void cla_adjustmatrix(NODEINST *ni, PORTPROTO *pp, XARRAY trans)
1340
 
{
1341
 
        REGISTER INTBIG ox, oy;
1342
 
        INTBIG onox, onoy, dx, dy;
1343
 
 
1344
 
        if (((CHANGE *)ni->changeaddr)->p5 == ni->rotation &&
1345
 
                ((CHANGE *)ni->changeaddr)->p6 == ni->transpose)
1346
 
        {
1347
 
                /* nodeinst did not rotate: adjust for port motion */
1348
 
                cla_oldportposition(ni, pp, &onox, &onoy);
1349
 
                portposition(ni, pp, &dx, &dy);
1350
 
                ox = (((CHANGE *)ni->changeaddr)->p1 + ((CHANGE *)ni->changeaddr)->p3) / 2;
1351
 
                oy = (((CHANGE *)ni->changeaddr)->p2 + ((CHANGE *)ni->changeaddr)->p4) / 2;
1352
 
#ifdef  CLA_DEBUG
1353
 
                if (cla_conlaydebug)
1354
 
                {
1355
 
                        ttyputmsg(M_("Node %s port %s was at (%s,%s), is at (%s,%s)"), describenodeinst(ni),
1356
 
                                pp->protoname, latoa(onox), latoa(onoy), latoa(dx), latoa(dy));
1357
 
                        ttyputmsg(M_("    Node moved (%s,%s)"), latoa(ox), latoa(oy));
1358
 
                }
1359
 
#endif
1360
 
                trans[2][0] = dx - onox + ox;   trans[2][1] = dy - onoy + oy;
1361
 
        } else
1362
 
        {
1363
 
                /* nodeinst rotated: adjust for nodeinst motion */
1364
 
                trans[2][0] = (ni->lowx + ni->highx) / 2;
1365
 
                trans[2][1] = (ni->lowy + ni->highy) / 2;
1366
 
        }
1367
 
}
1368
 
 
1369
 
/*
1370
 
 * routine to compute the position of portproto "pp" on nodeinst "ni" and
1371
 
 * place the center of the area in the parameters "x" and "y".  The position
1372
 
 * is the "old" position, as determined by any changes that may have occured
1373
 
 * to the nodeinst (and any sub-nodes).
1374
 
 */
1375
 
void cla_oldportposition(NODEINST *ni, PORTPROTO *pp, INTBIG *x, INTBIG *y)
1376
 
{
1377
 
        REGISTER INTBIG lox, hix, loy, hiy;
1378
 
        XARRAY localtran, subrot, temptr;
1379
 
        static POLYGON *poly = NOPOLYGON;
1380
 
 
1381
 
        /* make sure there is a polygon */
1382
 
        if (poly == NOPOLYGON) poly = allocstaticpolygon(4, cla_constraint->cluster);
1383
 
 
1384
 
        /* descend to the primitive node */
1385
 
        cla_makeoldrot(ni, subrot);
1386
 
        while (ni->proto->primindex == 0)
1387
 
        {
1388
 
                cla_makeoldtrans(ni, localtran);
1389
 
                transmult(localtran, subrot, temptr);
1390
 
                if (((CHANGE *)pp->changeaddr) != NOCHANGE &&
1391
 
                        ((CHANGE *)pp->changeaddr)->changetype == PORTPROTOMOD)
1392
 
                {
1393
 
                        /* special code for moved port prototypes */
1394
 
                        ni = (NODEINST *)((CHANGE *)pp->changeaddr)->p1;
1395
 
                        pp = (PORTPROTO *)((CHANGE *)pp->changeaddr)->p2;
1396
 
                } else
1397
 
                {
1398
 
                        ni = pp->subnodeinst;
1399
 
                        pp = pp->subportproto;
1400
 
                }
1401
 
                cla_makeoldrot(ni, localtran);
1402
 
                transmult(localtran, temptr, subrot);
1403
 
        }
1404
 
 
1405
 
        /* save the actual extents of the nodeinst */
1406
 
        lox = ni->lowx;   hix = ni->highx;
1407
 
        loy = ni->lowy;   hiy = ni->highy;
1408
 
 
1409
 
        /* if the node changed, reset it temporarily */
1410
 
        if (((CHANGE *)ni->changeaddr) != NOCHANGE &&
1411
 
                ((CHANGE *)ni->changeaddr)->changetype == NODEINSTMOD)
1412
 
        {
1413
 
                ni->lowx = ((CHANGE *)ni->changeaddr)->p1;
1414
 
                ni->highx = ((CHANGE *)ni->changeaddr)->p3;
1415
 
                ni->lowy = ((CHANGE *)ni->changeaddr)->p2;
1416
 
                ni->highy = ((CHANGE *)ni->changeaddr)->p4;
1417
 
        }
1418
 
 
1419
 
        /* now get the polygon describing the port */
1420
 
        shapetransportpoly(ni, pp, poly, subrot);
1421
 
 
1422
 
        /* reset the bounds of the nodeinst */
1423
 
        ni->lowx = lox;   ni->highx = hix;
1424
 
        ni->lowy = loy;   ni->highy = hiy;
1425
 
 
1426
 
        /* compute the center of the port */
1427
 
        getcenter(poly, x, y);
1428
 
}
1429
 
 
1430
 
void cla_makeoldrot(NODEINST *ni, XARRAY trans)
1431
 
{
1432
 
        REGISTER INTBIG nlx, nly, nhx, nhy;
1433
 
        REGISTER INTSML nr, nt;
1434
 
 
1435
 
        /* save values */
1436
 
        nlx = ni->lowx;         nly = ni->lowy;
1437
 
        nhx = ni->highx;        nhy = ni->highy;
1438
 
        nr  = ni->rotation;     nt  = ni->transpose;
1439
 
 
1440
 
        /* set to previous values if they changed */
1441
 
        if (((CHANGE *)ni->changeaddr) != NOCHANGE &&
1442
 
                ((CHANGE *)ni->changeaddr)->changetype == NODEINSTMOD)
1443
 
        {
1444
 
                ni->lowx      = ((CHANGE *)ni->changeaddr)->p1;
1445
 
                ni->lowy      = ((CHANGE *)ni->changeaddr)->p2;
1446
 
                ni->highx     = ((CHANGE *)ni->changeaddr)->p3;
1447
 
                ni->highy     = ((CHANGE *)ni->changeaddr)->p4;
1448
 
                ni->rotation  = (INTSML)((CHANGE *)ni->changeaddr)->p5;
1449
 
                ni->transpose = (INTSML)((CHANGE *)ni->changeaddr)->p6;
1450
 
        }
1451
 
 
1452
 
        /* create the former rotation matrix */
1453
 
        makerot(ni, trans);
1454
 
 
1455
 
        /* restore values */
1456
 
        ni->lowx     = nlx;     ni->lowy      = nly;
1457
 
        ni->highx    = nhx;     ni->highy     = nhy;
1458
 
        ni->rotation = nr;      ni->transpose = nt;
1459
 
}
1460
 
 
1461
 
void cla_makeoldtrans(NODEINST *ni, XARRAY trans)
1462
 
{
1463
 
        REGISTER INTBIG nlx, nly, nhx, nhy, ntlx, ntly, nthx, nthy;
1464
 
        REGISTER NODEPROTO *np;
1465
 
 
1466
 
        /* save values */
1467
 
        np = ni->proto;
1468
 
        nlx = ni->lowx;      nly = ni->lowy;
1469
 
        nhx = ni->highx;     nhy = ni->highy;
1470
 
        ntlx = np->lowx;      ntly = np->lowy;
1471
 
        nthx = np->highx;     nthy = np->highy;
1472
 
 
1473
 
        /* set to previous values if they changed */
1474
 
        if (((CHANGE *)ni->changeaddr) != NOCHANGE &&
1475
 
                ((CHANGE *)ni->changeaddr)->changetype == NODEINSTMOD)
1476
 
        {
1477
 
                ni->lowx  = ((CHANGE *)ni->changeaddr)->p1;
1478
 
                ni->lowy  = ((CHANGE *)ni->changeaddr)->p2;
1479
 
                ni->highx = ((CHANGE *)ni->changeaddr)->p3;
1480
 
                ni->highy = ((CHANGE *)ni->changeaddr)->p4;
1481
 
        }
1482
 
        if (((CHANGE *)np->changeaddr) != NOCHANGE &&
1483
 
                ((CHANGE *)np->changeaddr)->changetype == NODEPROTOMOD)
1484
 
        {
1485
 
                np->lowx  = ((CHANGE *)np->changeaddr)->p1;
1486
 
                np->highx = ((CHANGE *)np->changeaddr)->p2;
1487
 
                np->lowy  = ((CHANGE *)np->changeaddr)->p3;
1488
 
                np->highy = ((CHANGE *)np->changeaddr)->p4;
1489
 
        }
1490
 
 
1491
 
        /* create the former translation matrix */
1492
 
        maketrans(ni, trans);
1493
 
 
1494
 
        /* restore values */
1495
 
        ni->lowx  = nlx;     ni->lowy  = nly;
1496
 
        ni->highx = nhx;     ni->highy = nhy;
1497
 
        np->lowx  = ntlx;     np->lowy  = ntly;
1498
 
        np->highx = nthx;     np->highy = nthy;
1499
 
}
1500
 
 
1501
 
/*
1502
 
 * routine to re-compute the bounds of the facet "facet" (because an object
1503
 
 * has been added or removed from it) and store these bounds in the nominal
1504
 
 * size and the size of each instantiation of the facet.  It is also necessary
1505
 
 * to re-position each instantiation of the facet in its proper position list.
1506
 
 * If "forcedlook" is true, the facet is re-examined regardless of
1507
 
 * whether its size changed.
1508
 
 */
1509
 
void cla_computefacet(NODEPROTO *facet, BOOLEAN forcedlook)
1510
 
{
1511
 
        REGISTER NODEINST *ni, *lni;
1512
 
        REGISTER NODEPROTO *np, *oneparent;
1513
 
        INTBIG nlx, nhx, nly, nhy, offx, offy;
1514
 
        XARRAY trans;
1515
 
        REGISTER INTBIG dlx, dly, dhx, dhy, flx, fhx, fly, fhy;
1516
 
        REGISTER BOOLEAN mixed;
1517
 
        REGISTER CHANGE *c;
1518
 
        REGISTER LIBRARY *lib;
1519
 
 
1520
 
#ifdef  CLA_DEBUG
1521
 
        if (cla_conlaydebug)
1522
 
                ttyputmsg(M_("In computefacet on facet %s (fl=%ld)"),
1523
 
                        facet->cell->cellname, forcedlook);
1524
 
#endif
1525
 
        /* get current boundary of facet */
1526
 
        db_boundfacet(facet, &nlx,&nhx, &nly,&nhy);
1527
 
 
1528
 
        /* quit if it has not changed */
1529
 
        if (facet->lowx == nlx && facet->highx == nhx && facet->lowy == nly &&
1530
 
                facet->highy == nhy && !forcedlook) return;
1531
 
 
1532
 
        /* advance the change clock */
1533
 
        cla_changeclock += 4;
1534
 
 
1535
 
        /* get former size of facet from change information */
1536
 
        flx = facet->lowx;   fhx = facet->highx;
1537
 
        fly = facet->lowy;   fhy = facet->highy;
1538
 
        c = (CHANGE *)facet->changeaddr;
1539
 
        if (c != NOCHANGE && c->changetype == NODEPROTOMOD)
1540
 
        {
1541
 
                /* modification changes carry original size */
1542
 
                flx = c->p1;   fhx = c->p2;
1543
 
                fly = c->p3;   fhy = c->p4;
1544
 
        }
1545
 
 
1546
 
        /* update the facet size */
1547
 
        facet->lowx = nlx;   facet->highx = nhx;
1548
 
        facet->lowy = nly;   facet->highy = nhy;
1549
 
        facet->changeaddr = (char *)db_change((INTBIG)facet, NODEPROTOMOD, flx, fhx, fly, fhy, 0, 0);
1550
 
 
1551
 
        /* see if all instances of this facet are in the same location */
1552
 
        mixed = FALSE;
1553
 
        oneparent = NONODEPROTO;
1554
 
        lni = NONODEINST;
1555
 
        for(ni = facet->firstinst; ni != NONODEINST; ni = ni->nextinst)
1556
 
        {
1557
 
                oneparent = ni->parent;
1558
 
                if (lni != NONODEINST) if (ni->parent != lni->parent) mixed = TRUE;
1559
 
                lni = ni;
1560
 
        }
1561
 
 
1562
 
        /* if there are no constrained instances of the facet, no change */
1563
 
        if (oneparent == NONODEPROTO) return;
1564
 
 
1565
 
        /* if all parent facets the same, make changes to the instances */
1566
 
        if (!mixed && !forcedlook)
1567
 
        {
1568
 
#ifdef  CLA_DEBUG
1569
 
                if (cla_conlaydebug)
1570
 
                        ttyputmsg(M_("   Recomputing uniform parents of facet %s"),
1571
 
                                describenodeproto(facet));
1572
 
#endif
1573
 
                dlx = facet->lowx - flx;   dhx = facet->highx - fhx;
1574
 
                dly = facet->lowy - fly;   dhy = facet->highy - fhy;
1575
 
                for(ni = facet->firstinst; ni != NONODEINST; ni = ni->nextinst)
1576
 
                {
1577
 
                        makeangle(ni->rotation, ni->transpose, trans);
1578
 
                        xform(dhx+dlx, dhy+dly, &offx, &offy, trans);
1579
 
                        nlx = (dlx-dhx+offx)/2;  nhx = offx - nlx;
1580
 
                        nly = (dly-dhy+offy)/2;  nhy = offy - nly;
1581
 
                        if (cla_modifynodeinst(ni, nlx, nly, nhx, nhy, 0, 0, TRUE)) forcedlook = TRUE;
1582
 
                }
1583
 
                for(ni = facet->firstinst; ni != NONODEINST; ni = ni->nextinst)
1584
 
                        if (cla_modnodearcs(ni, 0, 0)) forcedlook = TRUE;
1585
 
                cla_computefacet(oneparent, forcedlook);
1586
 
                return;
1587
 
        }
1588
 
 
1589
 
        /*
1590
 
         * if instances are scattered or port motion has occured, examine
1591
 
         * entire database in proper recursive order and adjust facet sizes
1592
 
         */
1593
 
#ifdef  CLA_DEBUG
1594
 
        if (cla_conlaydebug)
1595
 
                ttyputmsg(M_("   Performing complex tree examination"));
1596
 
#endif
1597
 
        for(lib = el_curlib; lib != NOLIBRARY; lib = lib->nextlibrary)
1598
 
                for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1599
 
                        np->userbits &= ~(FACETMOD|FACETNOMOD);
1600
 
        facet->userbits |= FACETMOD;
1601
 
        for(lib = el_curlib; lib != NOLIBRARY; lib = lib->nextlibrary)
1602
 
                for(np = lib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
1603
 
        {
1604
 
                /* only want facets with no instances as roots of trees */
1605
 
                if (np->firstinst != NONODEINST) continue;
1606
 
 
1607
 
                /* now look recursively at the nodes in this facet */
1608
 
                (void)cla_lookdown(np);
1609
 
        }
1610
 
}
1611
 
 
1612
 
BOOLEAN cla_lookdown(NODEPROTO *start)
1613
 
{
1614
 
        REGISTER NODEINST *ni;
1615
 
        REGISTER NODEPROTO *np;
1616
 
        REGISTER INTBIG dlx, dhx, dly, dhy, flx, fhx, fly, fhy;
1617
 
        REGISTER BOOLEAN forcedlook, foundone;
1618
 
        INTBIG nlx, nhx, nly, nhy, offx, offy;
1619
 
        XARRAY trans;
1620
 
 
1621
 
        /* first look recursively to the bottom to see if this facet changed */
1622
 
        for(ni = start->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1623
 
                if (ni->proto->primindex == 0) ni->userbits |= MARKN; else
1624
 
                        ni->userbits &= ~MARKN;
1625
 
 
1626
 
        foundone = TRUE;
1627
 
        while (foundone)
1628
 
        {
1629
 
                foundone = FALSE;
1630
 
                for(ni = start->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1631
 
                {
1632
 
                        if ((ni->userbits & MARKN) == 0) continue;
1633
 
                        ni->userbits &= ~MARKN;
1634
 
                        np = ni->proto;
1635
 
 
1636
 
                        /* ignore recursive references (showing icon in contents) */
1637
 
/*                      if (np->cell == start->cell) continue; */
1638
 
 
1639
 
                        /* if this nodeinst is to change, mark the parent facet also */
1640
 
                        if ((np->userbits & FACETMOD) != 0) start->userbits |= FACETMOD;
1641
 
 
1642
 
                        /* don't look inside if the facet is certified */
1643
 
                        if ((np->userbits & (FACETNOMOD|FACETMOD)) != 0) continue;
1644
 
 
1645
 
                        /* look inside nodeinst to see if it changed */
1646
 
                        if (cla_lookdown(np)) start->userbits |= FACETMOD;
1647
 
                        foundone = TRUE;
1648
 
                }
1649
 
        }
1650
 
 
1651
 
        /* if this facet did not change, certify so and quit */
1652
 
        if ((start->userbits & FACETMOD) == 0)
1653
 
        {
1654
 
                start->userbits |= FACETNOMOD;
1655
 
                return(FALSE);
1656
 
        }
1657
 
 
1658
 
        /* mark those nodes that must change */
1659
 
        for(ni = start->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1660
 
        {
1661
 
                np = ni->proto;
1662
 
                ni->userbits &= ~(MARKN|TOUCHN);
1663
 
                if (np->primindex != 0) continue;
1664
 
/*              if (np->cell == start->cell) continue; */
1665
 
                if ((np->userbits & FACETMOD) == 0) continue;
1666
 
                ni->userbits |= MARKN | TOUCHN;
1667
 
        }
1668
 
#ifdef  CLA_DEBUG
1669
 
        if (cla_conlaydebug)
1670
 
                ttyputmsg(M_("      Complex tree search at facet %s"), describenodeproto(start));
1671
 
#endif
1672
 
        /* modify the nodes in this facet that changed */
1673
 
        forcedlook = FALSE;
1674
 
        foundone = TRUE;
1675
 
        while (foundone)
1676
 
        {
1677
 
                foundone = FALSE;
1678
 
                for(ni = start->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1679
 
                {
1680
 
                        if ((ni->userbits & MARKN) == 0) continue;
1681
 
                        ni->userbits &= ~MARKN;
1682
 
                        np = ni->proto;
1683
 
 
1684
 
                        /* determine original size of facet */
1685
 
                        if ((CHANGE *)np->changeaddr != NOCHANGE &&
1686
 
                                ((CHANGE *)np->changeaddr)->changetype == NODEPROTOMOD)
1687
 
                        {
1688
 
                                /* modification changes carry original size */
1689
 
                                flx = ((CHANGE *)np->changeaddr)->p1;
1690
 
                                fhx = ((CHANGE *)np->changeaddr)->p2;
1691
 
                                fly = ((CHANGE *)np->changeaddr)->p3;
1692
 
                                fhy = ((CHANGE *)np->changeaddr)->p4;
1693
 
                        } else
1694
 
                        {
1695
 
                                /* creation changes have no original size: use current size */
1696
 
                                flx = np->lowx;   fhx = np->highx;
1697
 
                                fly = np->lowy;   fhy = np->highy;
1698
 
                        }
1699
 
                        if (ni->highx-ni->lowx == np->highx-np->lowx && ni->highy-ni->lowy == np->highy-np->lowy)
1700
 
                                nlx = nhx = nly = nhy = 0; else
1701
 
                        {
1702
 
                                dlx = np->lowx - flx;   dhx = np->highx - fhx;
1703
 
                                dly = np->lowy - fly;   dhy = np->highy - fhy;
1704
 
                                makeangle(ni->rotation, ni->transpose, trans);
1705
 
                                xform(dhx+dlx, dhy+dly, &offx, &offy, trans);
1706
 
                                nlx = (dlx-dhx+offx)/2;  nhx = offx - nlx;
1707
 
                                nly = (dly-dhy+offy)/2;  nhy = offy - nly;
1708
 
                        }
1709
 
                        if (cla_modifynodeinst(ni, nlx, nly, nhx, nhy, 0, 0, TRUE)) forcedlook = TRUE;
1710
 
                        foundone = TRUE;
1711
 
                }
1712
 
        }
1713
 
 
1714
 
        /* now change the arcs in the nodes in this facet that changed */
1715
 
        foundone = TRUE;
1716
 
        while (foundone)
1717
 
        {
1718
 
                foundone = FALSE;
1719
 
                for(ni = start->firstnodeinst; ni != NONODEINST; ni = ni->nextnodeinst)
1720
 
                {
1721
 
                        if ((ni->userbits & TOUCHN) == 0) continue;
1722
 
                        ni->userbits &= ~TOUCHN;
1723
 
                        if (cla_modnodearcs(ni, 0, 0)) forcedlook = TRUE;
1724
 
                        foundone = TRUE;
1725
 
                }
1726
 
        }
1727
 
 
1728
 
        /* now change the size of this facet */
1729
 
        db_boundfacet(start, &nlx,&nhx, &nly,&nhy);
1730
 
 
1731
 
        /* quit if it has not changed */
1732
 
        if (start->lowx == nlx && start->highx == nhx && start->lowy == nly &&
1733
 
                start->highy == nhy && !forcedlook)
1734
 
        {
1735
 
                start->userbits |= FACETNOMOD;
1736
 
                return(FALSE);
1737
 
        }
1738
 
 
1739
 
        /* update the facet size */
1740
 
        start->changeaddr = (char *)db_change((INTBIG)start, NODEPROTOMOD,
1741
 
                start->lowx, start->highx, start->lowy, start->highy, 0, 0);
1742
 
        start->lowx = nlx;  start->highx = nhx;
1743
 
        start->lowy = nly;  start->highy = nhy;
1744
 
        return(TRUE);
1745
 
}