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

« back to all changes in this revision

Viewing changes to src/io/iocifout.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: iocifout.c
5
 
 * Input/output tool: CIF output
6
 
 * Written by: Steven M. Rubin, Static Free Software
7
 
 *
8
 
 * Copyright (c) 2000 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
 
 
31
 
#include "config.h"
32
 
#if IOCIF
33
 
 
34
 
#include "global.h"
35
 
#include "eio.h"
36
 
#include "egraphics.h"
37
 
#include "tecgen.h"
38
 
#include "edialogs.h"
39
 
#include "efunction.h"
40
 
 
41
 
#define FULLPOLYMERGE 1         /* uncomment to use older manhattan merging */
42
 
 
43
 
#define NMCHR   80
44
 
 
45
 
static INTBIG     io_prev_chr_sep, io_nchar;    /* for CRC checksum */
46
 
static UINTBIG    io_check_sum;                                 /* for CRC checksum */
47
 
static UINTBIG    io_cifcrctab[256];                    /* for CRC checksum */
48
 
static INTBIG     io_cif_resolution;                    /* for resolution tests */
49
 
static INTBIG     io_cif_polypoints;                    /* for points on a polygon tests */
50
 
static INTBIG    *io_cifoutputstate;                    /* current output state */
51
 
static INTBIG     io_cifoutoffx;                                /* offset for current facet - for highlight */
52
 
static INTBIG     io_cifoutoffy;                                /* offset for current facet - for highlight */
53
 
static NODEPROTO *io_cifoutcurnp;                               /* node proto of facet being written */
54
 
static BOOLEAN    io_zero_offset;                               /* Set if there is no centering */
55
 
static BOOLEAN    io_cif_highlightreserr;               /* Set to highlight resolution errors */
56
 
static INTBIG     io_reserr_count;                              /* count the resolution errors */
57
 
static char       io_cifoutcurlayer[200];               /* current layer name written out */
58
 
static INTBIG     io_cifoutfacetnumber;                 /* count of facets being written out */
59
 
static INTBIG     io_cifoutjobsize;                             /* number of facets to write out */
60
 
 
61
 
/* layer requests for grouping output layers */
62
 
#define NOLAYERREQ ((LAYERREQ *)-1)
63
 
 
64
 
typedef struct Ilayerreq
65
 
{
66
 
        TECHNOLOGY *tech;
67
 
        INTBIG      layer;
68
 
        char       *layername;
69
 
        struct Ilayerreq *nextlayerreq;
70
 
} LAYERREQ;
71
 
 
72
 
static LAYERREQ  *io_ciflayerreq = NOLAYERREQ;
73
 
static LAYERREQ  *io_ciflayerreqfree = NOLAYERREQ;
74
 
static LAYERREQ **io_ciflayerreqlist;
75
 
static INTBIG     io_ciflayerreqlisttotal = 0;
76
 
 
77
 
/* prototypes for local routines */
78
 
static void io_cifwritefacet(NODEPROTO*, BOOLEAN);
79
 
static void io_outputcifpoly(TECHNOLOGY*, POLYGON*, INTBIG, INTBIG, INTBIG, INTBIG, XARRAY, GEOM*);
80
 
static void io_cifprintf(char *msg, ...);
81
 
static void io_cifreserror(GEOM*, INTBIG, INTBIG, INTBIG, INTBIG, XARRAY);
82
 
static void io_cif_write_polygon(INTBIG, TECHNOLOGY*, INTBIG*, INTBIG*, INTBIG);
83
 
static void io_cif_show_reserror(INTBIG, INTBIG, INTBIG, INTBIG);
84
 
static INTBIG io_cif_outscale(INTBIG value);
85
 
static LAYERREQ *io_alloclayerreq(void);
86
 
static void io_freelayerreq(LAYERREQ *req);
87
 
static void io_includeciflayer(TECHNOLOGY *tech, INTBIG layer);
88
 
static void io_writeciflayer(char *layername);
89
 
static void io_cifoptionsdlog(void);
90
 
static INTBIG io_ciffindhighestlayer(NODEPROTO *np, INTBIG x, INTBIG y);
91
 
static int io_ciflayerreqascending(const void *e1, const void *e2);
92
 
 
93
 
/*
94
 
 * Routine to free all memory associated with this module.
95
 
 */
96
 
void io_freecifoutmemory(void)
97
 
{
98
 
        REGISTER LAYERREQ *req;
99
 
 
100
 
        while (io_ciflayerreq != NOLAYERREQ)
101
 
        {
102
 
                req = io_ciflayerreq;
103
 
                io_ciflayerreq = req->nextlayerreq;
104
 
                io_freelayerreq(req);
105
 
        }
106
 
        while (io_ciflayerreqfree != NOLAYERREQ)
107
 
        {
108
 
                req = io_ciflayerreqfree;
109
 
                io_ciflayerreqfree = req->nextlayerreq;
110
 
                efree((char *)req);
111
 
        }
112
 
        if (io_ciflayerreqlisttotal > 0) efree((char *)io_ciflayerreqlist);
113
 
}
114
 
 
115
 
/*
116
 
 * Routine to initialize CIF I/O.
117
 
 */
118
 
void io_initcif(void)
119
 
{
120
 
        extern COMCOMP io_cifp;
121
 
 
122
 
        DiaDeclareHook("cifopt", &io_cifp, io_cifoptionsdlog);
123
 
}
124
 
 
125
 
BOOLEAN io_writeciflibrary(LIBRARY *lib)
126
 
{
127
 
        char file[100], *truename;
128
 
        REGISTER char *name;
129
 
        REGISTER NODEPROTO *np;
130
 
        REGISTER VARIABLE *var;
131
 
        REGISTER TECHNOLOGY *tech;
132
 
        REGISTER LIBRARY *olib;
133
 
        REGISTER UINTBIG bytesread, i, j;
134
 
        static UINTBIG crcrow[8] = {0x04C11DB7, 0x09823B6E, 0x130476DC, 0x2608EDB8,
135
 
                0x4C11DB70, 0x9823B6E0, 0x34867077, 0x690CE0EE};
136
 
        extern DIALOG us_progressdialog;
137
 
 
138
 
        /* create the proper disk file for the CIF */
139
 
        if (lib->curnodeproto == NONODEPROTO)
140
 
        {
141
 
                ttyputerr(_("Must be editing a facet to generate CIF output"));
142
 
                return(TRUE);
143
 
        }
144
 
        (void)strcpy(file, lib->curnodeproto->cell->cellname);
145
 
        if (strcmp(&file[strlen(file)-4],".cif") != 0) (void)strcat(file, ".cif");
146
 
        name = truepath(file);
147
 
        io_fileout = xcreate(name, io_filetypecif, _("CIF File"), &truename);
148
 
        if (io_fileout == NULL)
149
 
        {
150
 
                if (truename != 0) ttyputerr(_("Cannot write %s"), truename);
151
 
                return(TRUE);
152
 
        }
153
 
 
154
 
        /* get current output state */
155
 
        io_cifoutputstate = io_getstatebits();
156
 
 
157
 
        /* get form of output */
158
 
        if ((io_cifoutputstate[0]&CIFOUTNORMALIZE) != 0) io_zero_offset = FALSE; else
159
 
                io_zero_offset = TRUE;
160
 
        if ((io_cifoutputstate[1]&CIFRESHIGH) != 0) io_cif_highlightreserr = TRUE; else
161
 
                io_cif_highlightreserr = FALSE;
162
 
 
163
 
        /* get cif resolution */
164
 
        var = getval((INTBIG)el_curtech, VTECHNOLOGY, VINTEGER, "IO_cif_resolution");
165
 
        if (var == NOVARIABLE) io_cif_resolution = 0; else
166
 
        {
167
 
                io_cif_resolution = var->addr;
168
 
                if (io_cif_resolution != 0 && io_cif_highlightreserr)
169
 
                        initerrorlogging("CIF Resolution");
170
 
        }
171
 
 
172
 
        /* get the number of allowable points on a polygon */
173
 
        var = getval((INTBIG)el_curtech, VTECHNOLOGY, VINTEGER, "IO_cif_polypoints");
174
 
        if (var == NOVARIABLE) io_cif_polypoints = MAXINTBIG; else
175
 
                io_cif_polypoints = var->addr;
176
 
 
177
 
        /* initialize cif merging facility if needed */
178
 
#ifndef FULLPOLYMERGE
179
 
        if ((io_cifoutputstate[0]&CIFOUTMERGE) != 0) mrginit();
180
 
#endif
181
 
 
182
 
        /* initialize the CRC checksum accumulation */
183
 
        for(i=0; i<256; i++)
184
 
        {
185
 
                io_cifcrctab[i] = 0;
186
 
                for(j=0; j<8; j++)
187
 
                        if (((1 << j) & i) != 0)
188
 
                                io_cifcrctab[i] = io_cifcrctab[i] ^ crcrow[j];
189
 
                io_cifcrctab[i] &= 0xFFFFFFFF;
190
 
        }
191
 
        io_nchar = 1;
192
 
        io_prev_chr_sep = 1;
193
 
        io_check_sum = io_cifcrctab[' '];
194
 
 
195
 
        /* initialize cache of CIF layer information */
196
 
        for(tech = el_technologies; tech != NOTECHNOLOGY; tech = tech->nexttechnology)
197
 
        {
198
 
                var = getval((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, "IO_cif_layer_names");
199
 
                if (var == NOVARIABLE) tech->temp1 = 0; else
200
 
                {
201
 
                        tech->temp1 = var->addr;
202
 
                        if (getlength(var) != tech->layercount)
203
 
                        {
204
 
                                ttyputerr(_("Warning: CIF layer information is bad for technology %s.  Use 'CIF Options' to fix it"),
205
 
                                        tech->techname);
206
 
                                tech->temp1 = 0;
207
 
                        }
208
 
                }
209
 
 
210
 
                var = getval((INTBIG)tech, VTECHNOLOGY, VSTRING|VISARRAY, "TECH_layer_names");
211
 
                tech->temp2 = (var == NOVARIABLE ? 0 : var->addr);
212
 
 
213
 
                /* if ignoring DRC mask layer, delete Generic technology layer names */
214
 
                if (tech == gen_tech && (io_cifoutputstate[0]&CIFOUTADDDRC) == 0) tech->temp1 = 0;
215
 
        }
216
 
 
217
 
        /* figure out how many facets will be written */
218
 
        io_cifoutfacetnumber = 0;
219
 
        for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
220
 
                for(np = olib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
221
 
                        np->temp1 = 0;
222
 
        io_cifwritefacet(lib->curnodeproto, TRUE);
223
 
        io_cifoutjobsize = io_cifoutfacetnumber;
224
 
        if (DiaInitDialog(&us_progressdialog)) return(TRUE);
225
 
        DiaPercent(1, 0);
226
 
        DiaSetText(2, _("Writing CIF..."));
227
 
 
228
 
        /* write the CIF */
229
 
        io_cifoutfacetnumber = 0;
230
 
        io_reserr_count = 0;
231
 
        io_cifbase = 100;
232
 
        for(olib = el_curlib; olib != NOLIBRARY; olib = olib->nextlibrary)
233
 
                for(np = olib->firstnodeproto; np != NONODEPROTO; np = np->nextnodeproto)
234
 
                        np->temp1 = 0;
235
 
        io_cifwritefacet(lib->curnodeproto, FALSE);
236
 
 
237
 
        /* clean up */
238
 
        if ((io_cifoutputstate[0]&CIFOUTNOTOPCALL) == 0)
239
 
                io_cifprintf("C %ld;\n", io_cifbase);
240
 
        io_cifprintf("E\n");
241
 
        xclose(io_fileout);
242
 
        DiaDoneDialog();
243
 
 
244
 
#ifndef FULLPOLYMERGE
245
 
        /* if doing polygon output */
246
 
        if ((io_cifoutputstate[0]&CIFOUTMERGE) != 0) mrgterm();
247
 
#endif
248
 
 
249
 
        /* tell the user that the file is written */
250
 
        ttyputmsg(_("%s written"), truename);
251
 
 
252
 
        /* complete the checksum accumulation */
253
 
        if (!io_prev_chr_sep)
254
 
        {
255
 
                io_check_sum = (io_check_sum << 8) ^
256
 
                        io_cifcrctab[((io_check_sum >> 24) ^ (unsigned char)' ') & 0xFF];
257
 
                io_nchar++;
258
 
        }
259
 
        bytesread = io_nchar;
260
 
        while (bytesread > 0)
261
 
        {
262
 
                io_check_sum = (io_check_sum << 8) ^
263
 
                        io_cifcrctab[((io_check_sum >> 24) ^ bytesread) & 0xFF];
264
 
                bytesread >>= 8;
265
 
        }
266
 
        io_check_sum = ~io_check_sum & 0xFFFFFFFF;
267
 
        ttyputmsg(_("(MOSIS CRC: %lu %ld)"), io_check_sum, io_nchar);
268
 
 
269
 
        /* complete error accumulation */
270
 
        if (io_cif_resolution != 0)
271
 
        {
272
 
                if (io_cif_highlightreserr)
273
 
                {
274
 
                        io_reserr_count = numerrors();
275
 
                        termerrorlogging(TRUE);
276
 
                }
277
 
                if (io_reserr_count != 0)
278
 
                        ttyputerr(_("WARNING: Found %ld resolution %s"), io_reserr_count,
279
 
                                makeplural(_("error"), io_reserr_count));
280
 
        }
281
 
 
282
 
        return(FALSE);
283
 
}
284
 
 
285
 
void io_cifwritefacet(NODEPROTO *np, BOOLEAN fake)
286
 
{
287
 
        REGISTER NODEINST *subni;
288
 
        REGISTER ARCINST *ai;
289
 
        REGISTER NODEPROTO *subnt, *onp;
290
 
        REGISTER PORTPROTO *pp, *subpp;
291
 
        REGISTER PORTARCINST *pi;
292
 
        REGISTER INTBIG i, j, total, validport, toplayer, toplayerfound;
293
 
        REGISTER INTBIG offx, offy, fun;
294
 
        REGISTER LAYERREQ *req;
295
 
        XARRAY trans, localtran, temp2, subrot, subt, subr, submat;
296
 
        INTBIG rx, ry, xpos, ypos, bx, by, subcornerx, subcornery;
297
 
        static POLYGON *poly = NOPOLYGON;
298
 
 
299
 
        /* get polygon */
300
 
        if (poly == NOPOLYGON) poly = allocstaticpolygon(4, io_tool->cluster);
301
 
 
302
 
        io_cifoutfacetnumber++;
303
 
        if (!fake)
304
 
        {
305
 
                /* stop if requested */
306
 
                if (stopping(STOPREASONCIF)) return;
307
 
 
308
 
                /* show progress */
309
 
                (void)initinfstr();
310
 
                (void)formatinfstr(_("Writing %s"), describenodeproto(np));
311
 
                DiaSetText(2, returninfstr());
312
 
                DiaPercent(1, io_cifoutfacetnumber * 100 / io_cifoutjobsize);
313
 
        }
314
 
 
315
 
        /* if there are any sub-facets that have not been written, write them */
316
 
        for(subni = np->firstnodeinst; subni != NONODEINST; subni = subni->nextnodeinst)
317
 
        {
318
 
                subnt = subni->proto;
319
 
                if (subnt->primindex != 0) continue;
320
 
 
321
 
                /* ignore recursive references (showing icon in contents) */
322
 
                if (subnt->cell == np->cell) continue;
323
 
 
324
 
                if ((subni->userbits & NEXPAND) == 0 && (io_cifoutputstate[0]&CIFOUTEXACT) != 0) continue;
325
 
 
326
 
                /* convert body facets to contents facets */
327
 
                onp = contentsview(subnt);
328
 
                if (onp != NONODEPROTO) subnt = onp;
329
 
 
330
 
                /* don't recurse if this facet has already been written */
331
 
                if (subnt->temp1 != 0) continue;
332
 
 
333
 
                /* recurse to the bottom */
334
 
                io_cifwritefacet(subnt, fake);
335
 
        }
336
 
 
337
 
        np->temp1 = ++io_cifbase;
338
 
        if (fake) return;
339
 
 
340
 
        io_cifoutcurnp = np;                    /* set global for highlighting */
341
 
 
342
 
        /* prepare to write the facet */
343
 
        if (io_zero_offset)
344
 
        {
345
 
                grabpoint(np, &io_cifoutoffx, &io_cifoutoffy);
346
 
                offx = io_cifoutoffx;
347
 
                offy = io_cifoutoffy;
348
 
        } else
349
 
        {
350
 
                offx = io_cifoutoffx = (np->lowx + np->highx) / 2;
351
 
                offy = io_cifoutoffy = (np->lowy + np->highy) / 2;
352
 
        }
353
 
        io_cifprintf("DS %ld 1 1;\n", io_cifbase);
354
 
        io_cifprintf("9 %s; (from library %s);\n", np->cell->cellname, np->cell->lib->libname);
355
 
 
356
 
        io_cifoutcurlayer[0] = 0;
357
 
        if ((io_cifoutputstate[0]&CIFOUTMERGE) == 0)
358
 
        {
359
 
                /* no polygon merging: sort by layer */
360
 
 
361
 
                /* determine which layers exist in this facet */
362
 
                while (io_ciflayerreq != NOLAYERREQ)
363
 
                {
364
 
                        req = io_ciflayerreq;
365
 
                        io_ciflayerreq = req->nextlayerreq;
366
 
                        io_freelayerreq(req);
367
 
                }
368
 
                for(subni = np->firstnodeinst; subni != NONODEINST; subni = subni->nextnodeinst)
369
 
                {
370
 
                        if ((subni->userbits&WIPED) != 0) continue;
371
 
                        subnt = subni->proto;
372
 
                        if (subnt->primindex == 0) continue;
373
 
                        i = nodepolys(subni, 0, NOWINDOWPART);
374
 
                        for(j=0; j<i; j++)
375
 
                        {
376
 
                                shapenodepoly(subni, j, poly);
377
 
                                io_includeciflayer(subnt->tech, poly->layer);
378
 
                        }
379
 
                }
380
 
                for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
381
 
                {
382
 
                        i = arcpolys(ai, NOWINDOWPART);
383
 
                        for(j=0; j<i; j++)
384
 
                        {
385
 
                                shapearcpoly(ai, j, poly);
386
 
                                io_includeciflayer(ai->proto->tech, poly->layer);
387
 
                        }
388
 
                }
389
 
 
390
 
                /* sort the requests by layer name */
391
 
                total = 0;
392
 
                for(req = io_ciflayerreq; req != NOLAYERREQ; req = req->nextlayerreq)
393
 
                        total++;
394
 
                if (total > io_ciflayerreqlisttotal)
395
 
                {
396
 
                        if (io_ciflayerreqlisttotal > 0)
397
 
                                efree((char *)io_ciflayerreqlist);
398
 
                        io_ciflayerreqlisttotal = 0;
399
 
                        io_ciflayerreqlist = (LAYERREQ **)emalloc(total * (sizeof (LAYERREQ *)),
400
 
                                io_tool->cluster);
401
 
                        if (io_ciflayerreqlist == 0) return;
402
 
                        io_ciflayerreqlisttotal = total;
403
 
                }
404
 
                total = 0;
405
 
                for(req = io_ciflayerreq; req != NOLAYERREQ; req = req->nextlayerreq)
406
 
                        io_ciflayerreqlist[total++] = req;
407
 
                esort(io_ciflayerreqlist, total, sizeof (LAYERREQ *), io_ciflayerreqascending);
408
 
                for(i=0; i<total-1; i++)
409
 
                        io_ciflayerreqlist[i]->nextlayerreq = io_ciflayerreqlist[i+1];
410
 
                if (total == 0) io_ciflayerreq = NOLAYERREQ; else
411
 
                {
412
 
                        io_ciflayerreq = io_ciflayerreqlist[0];
413
 
                        io_ciflayerreqlist[total-1]->nextlayerreq = NOLAYERREQ;
414
 
                }
415
 
 
416
 
                /* now write geometry by layer */
417
 
                for(req = io_ciflayerreq; req != NOLAYERREQ; req = req->nextlayerreq)
418
 
                {
419
 
                        if (req->layername == 0 || *req->layername == 0) continue;
420
 
 
421
 
                        /* write all primitive nodes in the facet */
422
 
                        for(subni = np->firstnodeinst; subni != NONODEINST; subni = subni->nextnodeinst)
423
 
                        {
424
 
                                /* don't draw anything if the node is wiped out */
425
 
                                if ((subni->userbits&WIPED) != 0) continue;
426
 
 
427
 
                                subnt = subni->proto;
428
 
                                if (subnt->primindex == 0) continue;
429
 
                                if (subnt->tech != req->tech) continue;
430
 
                                i = subni->rotation;
431
 
                                if (subni->transpose != 0) i = (i + 900) % 3600;
432
 
                                rx = ((cosine(i)>>14) * 100) >> 16;
433
 
                                ry = ((sine(i)>>14) * 100) >> 16;
434
 
                                makerot(subni, trans);
435
 
 
436
 
                                /* write a primitive nodeinst */
437
 
                                i = nodepolys(subni, 0, NOWINDOWPART);
438
 
                                for(j=0; j<i; j++)
439
 
                                {
440
 
                                        shapenodepoly(subni, j, poly);
441
 
                                        if (poly->layer != req->layer) continue;
442
 
                                        io_outputcifpoly(subnt->tech, poly, rx,
443
 
                                                (subni->transpose ? -ry : ry), offx, offy, trans, subni->geom);
444
 
                                }
445
 
                        }
446
 
 
447
 
                        /* write all of the arcs in the facet */
448
 
                        for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
449
 
                        {
450
 
                                if (ai->proto->tech != req->tech) continue;
451
 
                                i = arcpolys(ai, NOWINDOWPART);
452
 
                                for(j=0; j<i; j++)
453
 
                                {
454
 
                                        /* write the box describing the layer */
455
 
                                        shapearcpoly(ai, j, poly);
456
 
                                        if (poly->layer != req->layer) continue;
457
 
                                        io_outputcifpoly(ai->proto->tech, poly, 1, 0, offx, offy, el_matid, ai->geom);
458
 
                                }
459
 
                        }
460
 
                }
461
 
        } else
462
 
        {
463
 
#ifdef FULLPOLYMERGE
464
 
                mergeinit();
465
 
#endif
466
 
 
467
 
                /* doing polygon merging: just dump the geometry into the merging system */
468
 
                for(subni = np->firstnodeinst; subni != NONODEINST; subni = subni->nextnodeinst)
469
 
                {
470
 
                        /* don't draw anything if the node is wiped out */
471
 
                        if ((subni->userbits&WIPED) != 0) continue;
472
 
 
473
 
                        subnt = subni->proto;
474
 
                        if (subnt->primindex == 0) continue;
475
 
                        i = subni->rotation;
476
 
                        if (subni->transpose != 0) i = (i + 900) % 3600;
477
 
                        rx = ((cosine(i)>>14) * 100) >> 16;
478
 
                        ry = ((sine(i)>>14) * 100) >> 16;
479
 
                        makerot(subni, trans);
480
 
 
481
 
                        /* write a primitive nodeinst */
482
 
                        i = nodepolys(subni, 0, NOWINDOWPART);
483
 
                        for(j=0; j<i; j++)
484
 
                        {
485
 
                                shapenodepoly(subni, j, poly);
486
 
                                io_outputcifpoly(subnt->tech, poly, rx,
487
 
                                        (subni->transpose ? -ry : ry), offx, offy, trans, subni->geom);
488
 
                        }
489
 
                }
490
 
 
491
 
                /* write all of the arcs in the facet */
492
 
                for(ai = np->firstarcinst; ai != NOARCINST; ai = ai->nextarcinst)
493
 
                {
494
 
                        i = arcpolys(ai, NOWINDOWPART);
495
 
                        for(j=0; j<i; j++)
496
 
                        {
497
 
                                /* write the box describing the layer */
498
 
                                shapearcpoly(ai, j, poly);
499
 
                                io_outputcifpoly(ai->proto->tech, poly, 1, 0, offx, offy, el_matid, ai->geom);
500
 
                        }
501
 
                }
502
 
 
503
 
#ifdef FULLPOLYMERGE
504
 
                mergedone(io_cif_write_polygon);
505
 
#else
506
 
                mrgdonefacet(io_cif_write_polygon);
507
 
#endif
508
 
        }
509
 
 
510
 
        /* write all facet instances */
511
 
        for(subni = np->firstnodeinst; subni != NONODEINST; subni = subni->nextnodeinst)
512
 
        {
513
 
                subnt = subni->proto;
514
 
                if (subnt->primindex != 0) continue;
515
 
 
516
 
                /* ignore recursive references (showing icon in contents) */
517
 
                if (subnt->cell == np->cell) continue;
518
 
 
519
 
                i = subni->rotation;
520
 
                if (subni->transpose != 0) i = (i + 900) % 3600;
521
 
                rx = ((cosine(i)>>14) * 100) >> 16;
522
 
                ry = ((sine(i)>>14) * 100) >> 16;
523
 
                makerot(subni, trans);
524
 
 
525
 
                /* determine offset of facet */
526
 
                if (io_zero_offset)
527
 
                {
528
 
                        grabpoint(subni->proto, &bx, &by);
529
 
                        maketrans(subni, subt);
530
 
                        makerot(subni, subr);
531
 
                        transmult(subt, subr, submat);
532
 
                        xform(bx, by, &subcornerx, &subcornery, submat);
533
 
                        xpos = (subcornerx - offx);
534
 
                        ypos = (subcornery - offy);
535
 
                } else
536
 
                {
537
 
                        xpos = (subni->lowx + subni->highx)/2 - offx;
538
 
                        ypos = (subni->lowy + subni->highy)/2 - offy;
539
 
                }
540
 
                if ((subni->userbits&NEXPAND) != 0 || (io_cifoutputstate[0]&CIFOUTEXACT) == 0)
541
 
                {
542
 
                        /* check resolution of call */
543
 
                        if (io_cif_resolution != 0)
544
 
                        {
545
 
                                if ((xpos%io_cif_resolution) != 0 || (ypos%io_cif_resolution) != 0)
546
 
                                {
547
 
                                        io_cifprintf(_("(Call to symbol %ld does not resolve to grid);\n"),
548
 
                                                subnt->temp1);
549
 
                                        io_reserr_count++;
550
 
                                }
551
 
                        }
552
 
 
553
 
                        /* write a call to a facet */
554
 
                        io_cifprintf("C %ld R %ld %ld", subnt->temp1, rx, ry);
555
 
                        if (subni->transpose != 0) io_cifprintf(" M Y");
556
 
                        io_cifprintf(" T %ld %ld;\n", io_cif_outscale(xpos), io_cif_outscale(ypos));
557
 
                } else
558
 
                {
559
 
                        /* write the vectors that describe an unexpanded facet */
560
 
                        io_cifprintf("0V %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld;\n",
561
 
                                io_cif_outscale(subni->lowx-offx), io_cif_outscale(subni->lowy-offy),
562
 
                                        io_cif_outscale(subni->lowx-offx), io_cif_outscale(subni->highy-offy),
563
 
                                                io_cif_outscale(subni->highx-offx), io_cif_outscale(subni->highy-offy),
564
 
                                                        io_cif_outscale(subni->highx-offx), io_cif_outscale(subni->lowy-offy),
565
 
                                                                io_cif_outscale(subni->lowx-offx), io_cif_outscale(subni->lowy-offy));
566
 
                        io_cifprintf("2C \"%s\" T %ld %ld;\n", describenodeproto(subnt),
567
 
                                io_cif_outscale(xpos), io_cif_outscale(ypos));
568
 
                }
569
 
        }
570
 
 
571
 
        /* write the ports as labels */
572
 
        for(pp = np->firstportproto; pp != NOPORTPROTO; pp = pp->nextportproto)
573
 
        {
574
 
                /* get the coordinate of the port label */
575
 
                subni = pp->subnodeinst;   subpp = pp->subportproto;
576
 
                portposition(subni, subpp, &xpos, &ypos);
577
 
 
578
 
                /* find the primitive node on this port */
579
 
                makerot(subni, subrot);
580
 
                while (subni->proto->primindex == 0)
581
 
                {
582
 
                        maketrans(subni, localtran);
583
 
                        transmult(localtran, subrot, temp2);
584
 
                        subni = subpp->subnodeinst;
585
 
                        subpp = subpp->subportproto;
586
 
                        makerot(subni, localtran);
587
 
                        transmult(localtran, temp2, subrot);
588
 
                }
589
 
 
590
 
                /* get highest layer at this point */
591
 
                toplayer = io_ciffindhighestlayer(np, xpos, ypos);
592
 
                toplayerfound = 0;
593
 
 
594
 
                /* find valid layers on this node that surround the port */
595
 
                validport = 0;
596
 
                total = nodepolys(subni, 0, NOWINDOWPART);
597
 
                for(i=0; i<total; i++)
598
 
                {
599
 
                        shapenodepoly(subni, i, poly);
600
 
                        if (poly->layer < 0) continue;
601
 
                        fun = layerfunction(poly->tech, poly->layer);
602
 
                        if ((fun&LFPSEUDO) != 0) continue;
603
 
                        xformpoly(poly, subrot);
604
 
                        if (!isinside(xpos-1, ypos, poly)) continue;
605
 
                        if (!isinside(xpos+1, ypos, poly)) continue;
606
 
                        if (!isinside(xpos, ypos-1, poly)) continue;
607
 
                        if (!isinside(xpos, ypos+1, poly)) continue;
608
 
                        if (poly->layer == toplayer) toplayerfound = 1;
609
 
                        validport = 1;
610
 
                        break;
611
 
                }
612
 
                if (validport == 0)
613
 
                {
614
 
                        /* look for connected arcs */
615
 
                        subpp = pp;
616
 
                        transid(subrot);
617
 
                        for(;;)
618
 
                        {
619
 
                                /* look for layers at this level of hierarchy */
620
 
                                for(pi = subpp->subnodeinst->firstportarcinst; pi != NOPORTARCINST; pi = pi->nextportarcinst)
621
 
                                {
622
 
                                        ai = pi->conarcinst;
623
 
                                        total = arcpolys(ai, NOWINDOWPART);
624
 
                                        for(i=0; i<total; i++)
625
 
                                        {
626
 
                                                shapearcpoly(ai, i, poly);
627
 
                                                if (poly->layer < 0) continue;
628
 
                                                fun = layerfunction(poly->tech, poly->layer);
629
 
                                                if ((fun&LFPSEUDO) != 0) continue;
630
 
                                                xformpoly(poly, subrot);
631
 
                                                if (!isinside(xpos-1, ypos, poly)) continue;
632
 
                                                if (!isinside(xpos+1, ypos, poly)) continue;
633
 
                                                if (!isinside(xpos, ypos-1, poly)) continue;
634
 
                                                if (!isinside(xpos, ypos+1, poly)) continue;
635
 
                                                if (poly->layer == toplayer) toplayerfound = 1;
636
 
                                                validport = 1;
637
 
                                                break;
638
 
                                        }
639
 
                                        if (validport != 0) break;
640
 
                                }
641
 
                                if (validport != 0) break;
642
 
 
643
 
                                /* not found on this level: descend and look again */
644
 
                                if (subpp->subnodeinst->proto->primindex != 0) break;
645
 
                                maketrans(subpp->subnodeinst, localtran);
646
 
                                transmult(localtran, subrot, temp2);
647
 
                                makerot(subpp->subnodeinst, localtran);
648
 
                                transmult(localtran, temp2, subrot);
649
 
                                subpp = subpp->subportproto;
650
 
                        }
651
 
                }
652
 
                if (validport != 0)
653
 
                {
654
 
                        if (toplayerfound == 0)
655
 
                                ttyputmsg(_("Warning: facet %s, export '%s' obscured by higher layer"),
656
 
                                        describenodeproto(np), pp->protoname);
657
 
                        io_cifprintf("94 %s %ld %ld;\n", pp->protoname, io_cif_outscale(xpos-offx),
658
 
                                io_cif_outscale(ypos-offy));
659
 
                }
660
 
        }
661
 
 
662
 
        io_cifprintf("DF;\n");
663
 
}
664
 
 
665
 
int io_ciflayerreqascending(const void *e1, const void *e2)
666
 
{
667
 
        REGISTER LAYERREQ *lr1, *lr2;
668
 
        REGISTER char *lrname1, *lrname2;
669
 
 
670
 
        lr1 = *((LAYERREQ **)e1);
671
 
        lr2 = *((LAYERREQ **)e2);
672
 
        lrname1 = lr1->layername;
673
 
        if (lrname1 == 0) lrname1 = "";
674
 
        lrname2 = lr2->layername;
675
 
        if (lrname2 == 0) lrname2 = "";
676
 
        return(namesame(lrname1, lrname2));
677
 
}
678
 
 
679
 
INTBIG io_ciffindhighestlayer(NODEPROTO *np, INTBIG x, INTBIG y)
680
 
{
681
 
        REGISTER INTBIG sea, i, tot, first, bestheight, bestlayer;
682
 
        INTBIG height, thickness;
683
 
        REGISTER GEOM *geom;
684
 
        REGISTER NODEINST *ni;
685
 
        REGISTER ARCINST *ai;
686
 
        static POLYGON *poly = NOPOLYGON;
687
 
 
688
 
        if (poly == NOPOLYGON) poly = allocstaticpolygon(4, io_tool->cluster);
689
 
        sea = initsearch(x, x, y, y, np);
690
 
        first = 1;
691
 
        for(;;)
692
 
        {
693
 
                geom = nextobject(sea);
694
 
                if (geom == NOGEOM) break;
695
 
                if (geom->entryisnode)
696
 
                {
697
 
                        ni = geom->entryaddr.ni;
698
 
                        if (ni->proto->primindex == 0) continue;
699
 
                        tot = nodepolys(ni, 0, NOWINDOWPART);
700
 
                        for(i=0; i<tot; i++)
701
 
                        {
702
 
                                shapenodepoly(ni, i, poly);
703
 
                                if (!isinside(x, y, poly)) continue;
704
 
                                if (get3dfactors(poly->tech, poly->layer, &height, &thickness))
705
 
                                        continue;
706
 
 
707
 
                                /* LINTED "bestheight" used in proper order */
708
 
                                if (first != 0 || height > bestheight)
709
 
                                {
710
 
                                        bestheight = height;
711
 
                                        bestlayer = poly->layer;
712
 
                                        first = 0;
713
 
                                }
714
 
                        }
715
 
                } else
716
 
                {
717
 
                        ai = geom->entryaddr.ai;
718
 
                        tot = arcpolys(ai, NOWINDOWPART);
719
 
                        for(i=0; i<tot; i++)
720
 
                        {
721
 
                                shapearcpoly(ai, i, poly);
722
 
                                if (!isinside(x, y, poly)) continue;
723
 
                                if (get3dfactors(poly->tech, poly->layer, &height, &thickness))
724
 
                                        continue;
725
 
                                if (first != 0 || height > bestheight)
726
 
                                {
727
 
                                        bestheight = height;
728
 
                                        bestlayer = poly->layer;
729
 
                                        first = 0;
730
 
                                }
731
 
                        }
732
 
                }
733
 
        }
734
 
        if (first != 0) return(0);
735
 
        return(bestlayer);
736
 
}
737
 
 
738
 
/*
739
 
 * Routine to dump the layer name (if it has changed).
740
 
 */
741
 
void io_writeciflayer(char *layername)
742
 
{
743
 
        if (strcmp(layername, io_cifoutcurlayer) == 0) return;
744
 
        io_cifprintf("L %s;\n", layername);
745
 
        strcpy(io_cifoutcurlayer, layername);
746
 
}
747
 
 
748
 
/*
749
 
 * routine to write polygon "poly" to the CIF file.  The polygon is from
750
 
 * technology "tech", is rotated by the factor "rx" and "ry", and is offset
751
 
 * by "offx" and "offy"
752
 
 */
753
 
void io_outputcifpoly(TECHNOLOGY *tech, POLYGON *poly, INTBIG rx, INTBIG ry,
754
 
        INTBIG offx, INTBIG offy, XARRAY trans, GEOM *geom)
755
 
{
756
 
        REGISTER INTBIG r, k, bloat;
757
 
        INTBIG xl, xh, yl, yh, xpos, ypos;
758
 
        REGISTER char *layername;
759
 
 
760
 
        /* get bloating for this layer */
761
 
        if (poly->layer < 0 || tech->temp1 == 0) return;
762
 
        (void)initinfstr();
763
 
        (void)addstringtoinfstr(tech->techname);
764
 
        (void)addtoinfstr(':');
765
 
        (void)addstringtoinfstr(((char **)tech->temp2)[poly->layer]);
766
 
        bloat = io_getoutputbloat(returninfstr());
767
 
 
768
 
        /* get the CIF layer, stop if none */
769
 
        layername = ((char **)tech->temp1)[poly->layer];
770
 
        if (*layername == 0) return;
771
 
 
772
 
        switch (poly->style)
773
 
        {
774
 
                case DISC:
775
 
                        xformpoly(poly, trans);
776
 
                        r = computedistance(poly->xv[0], poly->yv[0], poly->xv[1], poly->yv[1]);
777
 
                        if (r <= 0) break;
778
 
 
779
 
                        /* write the layer name */
780
 
                        io_writeciflayer(layername);
781
 
 
782
 
                        /* write the round-flash */
783
 
                        io_cifprintf(" R %ld %ld %ld;\n", r+bloat, io_cif_outscale(poly->xv[0]-offx),
784
 
                                io_cif_outscale(poly->yv[0]-offy));
785
 
                        break;
786
 
 
787
 
                default:
788
 
#ifdef FULLPOLYMERGE
789
 
                        if ((io_cifoutputstate[0]&CIFOUTMERGE) != 0)
790
 
                        {
791
 
                                xformpoly(poly, trans);
792
 
                                for(k=0; k<poly->count; k++)
793
 
                                {
794
 
                                        poly->xv[k] -= offx;
795
 
                                        poly->yv[k] -= offy;
796
 
                                }
797
 
                                mergestorepolygon(poly->layer, tech, poly);
798
 
                                break;
799
 
                        }
800
 
#endif
801
 
 
802
 
                        if (isbox(poly, &xl,&xh, &yl,&yh))
803
 
                        {
804
 
                                /* ignore zero-size polygons */
805
 
                                if (xh == xl || yh == yl) return;
806
 
 
807
 
#ifndef FULLPOLYMERGE
808
 
                                if ((io_cifoutputstate[0]&CIFOUTMERGE) != 0)
809
 
                                {
810
 
                                        /* do polygon format output */
811
 
                                        xform((xl+xh)/2, (yl+yh)/2, &xpos, &ypos, trans);
812
 
                                        if (rx != 0 && ry == 0)
813
 
                                        {
814
 
                                                /* no rotation needed */
815
 
                                                mrgstorebox(poly->layer, tech, xh-xl+bloat, yh-yl+bloat,
816
 
                                                        xpos-offx, ypos-offy);
817
 
                                                return;
818
 
                                        }
819
 
                                        if (rx == 0 && ry != 0)
820
 
                                        {
821
 
                                                /* rotate through 90 degrees */
822
 
                                                mrgstorebox(poly->layer, tech, yh-yl+bloat, xh-xl+bloat,
823
 
                                                        xpos-offx, ypos-offy);
824
 
                                                return;
825
 
                                        }
826
 
                                        /* nonmanhattan or worse .. fall into direct output case */
827
 
                                }
828
 
#endif
829
 
 
830
 
                                /* write the layer name */
831
 
                                io_writeciflayer(layername);
832
 
 
833
 
                                /* non-merged box: highlight resolution errors */
834
 
                                io_cifreserror(geom, xh-xl+bloat, yh-yl+bloat, (xl+xh)/2, (yl+yh)/2, trans);
835
 
 
836
 
                                /* want individual box output */
837
 
                                xform((xl+xh)/2, (yl+yh)/2, &xpos, &ypos, trans);
838
 
                                io_cifprintf(" B %ld %ld %ld %ld", io_cif_outscale(xh-xl+bloat),
839
 
                                        io_cif_outscale(yh-yl+bloat), io_cif_outscale(xpos-offx),
840
 
                                                io_cif_outscale(ypos-offy));
841
 
                                if (rx <= 0 || ry != 0) io_cifprintf(" %ld %ld", rx, ry);
842
 
                                io_cifprintf(";\n");
843
 
                        } else
844
 
                        {
845
 
                                /* write the layer name */
846
 
                                io_writeciflayer(layername);
847
 
 
848
 
                                xformpoly(poly, trans);
849
 
                                if (bloat != 0)
850
 
                                {
851
 
                                        ttyputmsg(_("Warning: complex CIF polygon cannot be bloated"));
852
 
                                        io_cifprintf(_("(NEXT POLYGON CANNOT BE BLOATED);\n"));
853
 
                                }
854
 
                                if (poly->count == 1)
855
 
                                        io_cifprintf(" 0V %ld %ld %ld %ld;\n", io_cif_outscale(poly->xv[0]-offx),
856
 
                                                io_cif_outscale(poly->yv[0]-offy), io_cif_outscale(poly->xv[0]-offx),
857
 
                                                        io_cif_outscale(poly->yv[0]-offy)); else
858
 
                                if (poly->count == 2)
859
 
                                        io_cifprintf(" 0V %ld %ld %ld %ld;\n", io_cif_outscale(poly->xv[0]-offx),
860
 
                                                io_cif_outscale(poly->yv[0]-offy), io_cif_outscale(poly->xv[1]-offx),
861
 
                                                        io_cif_outscale(poly->yv[1]-offy)); else
862
 
                                {
863
 
                                        /*
864
 
                                         * Now call routine to write the polygon:
865
 
                                         *    - break long lines
866
 
                                         *    - check for resolution errors
867
 
                                         */
868
 
                                        for (k = 0; k < poly->count; k++)
869
 
                                        {
870
 
                                                /*
871
 
                                                 * WARNING: this changes poly!
872
 
                                                 */
873
 
                                                poly->xv[k] -= offx;
874
 
                                                poly->yv[k] -= offy;
875
 
                                        }
876
 
                                        io_cif_write_polygon(poly->layer, tech, poly->xv, poly->yv, poly->count);
877
 
                                }
878
 
                        }
879
 
                        return;
880
 
        }
881
 
 
882
 
#if 0           /* code to handle certain polygons without valid CIF layers */
883
 
        switch (poly->style)
884
 
        {
885
 
                case CLOSEDRECT:
886
 
                        xformpoly(poly, trans);
887
 
                        getbbox(poly, &xl,&xh, &yl,&yh);
888
 
                        io_cifprintf("0V %ld %ld", io_cif_outscale(xl-offx), io_cif_outscale(yl-offy));
889
 
                        io_cifprintf(" %ld %ld", io_cif_outscale(xl-offx), io_cif_outscale(yh-offy));
890
 
                        io_cifprintf(" %ld %ld", io_cif_outscale(xh-offx), io_cif_outscale(yh-offy));
891
 
                        io_cifprintf(" %ld %ld;\n", io_cif_outscale(xh-offx), io_cif_outscale(yl-offy));
892
 
                        return;
893
 
 
894
 
                case OPENED:
895
 
                case OPENEDT1:
896
 
                case OPENEDT2:
897
 
                case OPENEDT3:
898
 
                case CLOSED:
899
 
                        xformpoly(poly, trans);
900
 
                        io_cifprintf("0V");
901
 
                        for(k=0; k<poly->count; k++)
902
 
                                io_cifprintf(" %ld %ld", io_cif_outscale(poly->xv[k]-offx), io_cif_outscale(poly->yv[k]-offy));
903
 
                        if (poly->style == CLOSED)
904
 
                                io_cifprintf(" %ld %ld", io_cif_outscale(poly->xv[k]-offx), io_cif_outscale(poly->yv[k]-offy));
905
 
                        io_cifprintf(";\n");
906
 
                        return;
907
 
 
908
 
                case VECTORS:
909
 
                        xformpoly(poly, trans);
910
 
                        for(k=0; k<poly->count; k += 2)
911
 
                        {
912
 
                                io_cifprintf("0V %ld %ld", io_cif_outscale(poly->xv[k]-offx),
913
 
                                        io_cif_outscale(poly->yv[k]-offy));
914
 
                                io_cifprintf(" %ld %ld;\n", io_cif_outscale(poly->xv[k+1]-offx),
915
 
                                        io_cif_outscale(poly->yv[k+1]-offy));
916
 
                        }
917
 
                        return;
918
 
        }
919
 
#endif
920
 
}
921
 
 
922
 
/*
923
 
 * routine to send a line to the CIF output file and to accumulate
924
 
 * checksum information.
925
 
 */
926
 
void io_cifprintf(char *msg, ...)
927
 
{
928
 
        va_list ap;
929
 
        char temp[200], *cp;
930
 
        unsigned char c;
931
 
 
932
 
        var_start(ap, msg);
933
 
        evsnprintf(temp, 200, msg, ap);
934
 
        va_end(ap);
935
 
 
936
 
        /* accumulate CRC */
937
 
        for(cp = temp; *cp != 0; cp++)
938
 
        {
939
 
                c = *cp;
940
 
                if (c > ' ')
941
 
                {
942
 
                        io_check_sum = (io_check_sum << 8) ^
943
 
                                io_cifcrctab[((io_check_sum >> 24) ^ c) & 0xFF];
944
 
                        io_prev_chr_sep = 0;
945
 
                        io_nchar++;
946
 
                } else if (io_prev_chr_sep == 0)
947
 
                {
948
 
                        io_check_sum = (io_check_sum << 8) ^
949
 
                                io_cifcrctab[((io_check_sum >> 24) ^ (unsigned char)' ') & 0xFF];
950
 
                        io_prev_chr_sep = 1;
951
 
                        io_nchar++;
952
 
                }
953
 
        }
954
 
 
955
 
        xprintf(io_fileout, "%s", temp);
956
 
}
957
 
 
958
 
/* routine which highlights box which doesn't resolve */
959
 
void io_cifreserror(GEOM *pos, INTBIG length, INTBIG width, INTBIG xc, INTBIG yc, XARRAY trans)
960
 
{
961
 
        INTBIG ptx[4], pty[4], x, y;
962
 
        REGISTER INTBIG i;
963
 
        void *err;
964
 
 
965
 
        /* stop if no resolution check or no geometry module */
966
 
        if (io_cif_resolution == 0 || pos == NOGEOM) return;
967
 
 
968
 
        ptx[0] = ptx[1] = xc - (length/2);
969
 
        ptx[2] = ptx[3] = xc + (length/2);
970
 
        pty[0] = pty[3] = yc + (width/2);
971
 
        pty[1] = pty[2] = yc - (width/2);
972
 
        for(i=0; i<4; i++)
973
 
        {
974
 
                xform(ptx[i], pty[i], &x, &y, trans);
975
 
 
976
 
                /* see if it resolves to grid */
977
 
                if ((x % io_cif_resolution) != 0 || (y % io_cif_resolution) != 0)
978
 
                {
979
 
                        /* highlight the object */
980
 
                        if (io_cif_highlightreserr)
981
 
                        {
982
 
                                err = logerror("Resolution error", geomparent(pos), 0);
983
 
                                addgeomtoerror(err, pos, TRUE, 0, 0);
984
 
                        }
985
 
                        io_reserr_count++;
986
 
                        return;
987
 
                }
988
 
        }
989
 
}
990
 
 
991
 
void io_cif_write_polygon(INTBIG layer, TECHNOLOGY *tech, INTBIG *xbuf, INTBIG *ybuf,
992
 
        INTBIG count)
993
 
{
994
 
        INTBIG buflen, prlen, i;
995
 
        INTBIG tmpx, tmpy;
996
 
        char outbuf[NMCHR+2], prbuf[40], *layername; /* declare buffers */
997
 
 
998
 
        /* write the layer name */
999
 
        if (layer < 0 || tech->temp1 == 0) return;
1000
 
        layername = ((char **)tech->temp1)[layer];
1001
 
        if (*layername == 0) return;
1002
 
        io_writeciflayer(layername);
1003
 
 
1004
 
        /* set up first line */
1005
 
        (void)sprintf(outbuf, "P ");
1006
 
        buflen = strlen(outbuf);
1007
 
 
1008
 
        /* check the number of points on the polygon */
1009
 
        if (count > io_cif_polypoints)
1010
 
                ttyputerr(_("WARNING: Polygon has too many points (%ld)"), count);
1011
 
 
1012
 
        /* search for any resolution errors on this polygon */
1013
 
        /* highlight any edges that don't resolve */
1014
 
        if (io_cif_resolution != 0)
1015
 
        {
1016
 
                tmpx = xbuf[count-1];
1017
 
                tmpy = ybuf[count-1];
1018
 
                for (i = 0; i < count; i++)
1019
 
                {
1020
 
                        if ((tmpx%io_cif_resolution) != 0 && tmpx == xbuf[i])
1021
 
                        {
1022
 
                                io_cif_show_reserror(tmpx+io_cifoutoffx, tmpy+io_cifoutoffy,
1023
 
                                        xbuf[i]+io_cifoutoffx, ybuf[i]+io_cifoutoffy);
1024
 
                        } else if ((tmpy%io_cif_resolution) != 0 && tmpy == ybuf[i])
1025
 
                        {
1026
 
                                io_cif_show_reserror(tmpx+io_cifoutoffx, tmpy+io_cifoutoffy,
1027
 
                                        xbuf[i]+io_cifoutoffx, ybuf[i]+io_cifoutoffy);
1028
 
                        }
1029
 
                        tmpx = xbuf[i];
1030
 
                        tmpy = ybuf[i];
1031
 
                }
1032
 
        }
1033
 
 
1034
 
        for(i=0; i<count; i++)
1035
 
        {
1036
 
                (void)sprintf(prbuf, " %ld %ld", io_cif_outscale(xbuf[i]),
1037
 
                        io_cif_outscale(ybuf[i]));
1038
 
                prlen = strlen(prbuf); /* get length of coord. pair */
1039
 
 
1040
 
                /* if we have done the last point */
1041
 
                if (i == count-1)
1042
 
                {
1043
 
                        if (prlen + buflen < NMCHR-1) /* if space in buffer */
1044
 
                        {
1045
 
                                (void)strcat(outbuf, prbuf); /* concatenate strings */
1046
 
                                io_cifprintf("%s;\n", outbuf); /* write the buffer */
1047
 
                        } else
1048
 
                        {
1049
 
                                /* write as two lines */
1050
 
                                io_cifprintf("%s\n", outbuf);
1051
 
                                io_cifprintf("  %s;\n", prbuf);
1052
 
                        }
1053
 
                } else
1054
 
                {
1055
 
                        /* not yet done */
1056
 
                        if (prlen + buflen < NMCHR) /* if small enough */
1057
 
                        {
1058
 
                                /* append to buffer */
1059
 
                                (void)strcat(outbuf, prbuf);
1060
 
                                buflen = strlen(outbuf);
1061
 
                        } else
1062
 
                        {
1063
 
                                /* we must write the buffer out, and re-initialize it */
1064
 
                                io_cifprintf("%s\n", outbuf);
1065
 
                                (void)sprintf(outbuf, "  %s", prbuf);
1066
 
                                buflen = strlen(outbuf);
1067
 
                        }
1068
 
                }
1069
 
        }
1070
 
}
1071
 
 
1072
 
void io_cif_show_reserror(INTBIG x1, INTBIG y1, INTBIG x2, INTBIG y2)
1073
 
{
1074
 
        REGISTER void *err;
1075
 
 
1076
 
        if (!io_cif_highlightreserr) return;
1077
 
 
1078
 
        /* show resolution error if it is in the current window */
1079
 
        err = logerror("Resolution error", io_cifoutcurnp, 0);
1080
 
        addlinetoerror(err, x1, y1, x2, y2);
1081
 
        io_reserr_count++;
1082
 
}
1083
 
 
1084
 
INTBIG io_cif_outscale(INTBIG value)
1085
 
{
1086
 
        float v;
1087
 
 
1088
 
        v = scaletodispunit(value, DISPUNITCMIC);
1089
 
        return(roundfloat(v));
1090
 
}
1091
 
 
1092
 
void io_includeciflayer(TECHNOLOGY *tech, INTBIG layer)
1093
 
{
1094
 
        REGISTER LAYERREQ *req;
1095
 
 
1096
 
        /* stop now if the layer is already in the list */
1097
 
        for(req = io_ciflayerreq; req != NOLAYERREQ; req = req->nextlayerreq)
1098
 
                if (req->tech == tech && req->layer == layer) return;
1099
 
 
1100
 
        /* add to the list */
1101
 
        req = io_alloclayerreq();
1102
 
        if (req == NOLAYERREQ) return;
1103
 
        req->tech = tech;
1104
 
        req->layer = layer;
1105
 
        if (layer < 0 || tech->temp1 == 0) req->layername = 0; else
1106
 
                req->layername = ((char **)tech->temp1)[layer];
1107
 
        req->nextlayerreq = io_ciflayerreq;
1108
 
        io_ciflayerreq = req;
1109
 
}
1110
 
 
1111
 
LAYERREQ *io_alloclayerreq(void)
1112
 
{
1113
 
        REGISTER LAYERREQ *req;
1114
 
 
1115
 
        if (io_ciflayerreqfree == NOLAYERREQ)
1116
 
        {
1117
 
                req = (LAYERREQ *)emalloc(sizeof (LAYERREQ), io_tool->cluster);
1118
 
                if (req == 0) return(NOLAYERREQ);
1119
 
        } else
1120
 
        {
1121
 
                req = io_ciflayerreqfree;
1122
 
                io_ciflayerreqfree = req->nextlayerreq;
1123
 
        }
1124
 
        return(req);
1125
 
}
1126
 
 
1127
 
void io_freelayerreq(LAYERREQ *req)
1128
 
{
1129
 
        req->nextlayerreq = io_ciflayerreqfree;
1130
 
        io_ciflayerreqfree = req;
1131
 
}
1132
 
 
1133
 
/* CIF Options */
1134
 
static DIALOGITEM io_cifoptionsdialogitems[] =
1135
 
{
1136
 
 /*  1 */ {0, {224,380,248,452}, BUTTON, N_("OK")},
1137
 
 /*  2 */ {0, {224,240,248,312}, BUTTON, N_("Cancel")},
1138
 
 /*  3 */ {0, {8,8,248,223}, SCROLL, ""},
1139
 
 /*  4 */ {0, {8,232,24,312}, MESSAGE, N_("CIF Layer:")},
1140
 
 /*  5 */ {0, {8,316,24,454}, EDITTEXT, ""},
1141
 
 /*  6 */ {0, {32,232,48,454}, CHECK, N_("Output Mimics Display")},
1142
 
 /*  7 */ {0, {56,232,72,454}, CHECK, N_("Output Merges Boxes")},
1143
 
 /*  8 */ {0, {148,232,164,454}, CHECK, N_("Input Squares Wires")},
1144
 
 /*  9 */ {0, {100,232,116,454}, CHECK, N_("Output Instantiates Top Level")},
1145
 
 /* 10 */ {0, {196,240,212,384}, MESSAGE, N_("Output resolution:")},
1146
 
 /* 11 */ {0, {196,388,212,454}, EDITTEXT, ""},
1147
 
 /* 12 */ {0, {172,232,188,436}, POPUP, ""},
1148
 
 /* 13 */ {0, {124,232,140,454}, CHECK, N_("Normalize Coordinates")},
1149
 
 /* 14 */ {0, {76,248,92,454}, MESSAGE, N_("(time consuming)")}
1150
 
};
1151
 
static DIALOG io_cifoptionsdialog = {{50,75,307,538}, N_("CIF Options"), 0, 14, io_cifoptionsdialogitems};
1152
 
 
1153
 
/* special items for the "CIF Options" dialog: */
1154
 
#define DCFO_LAYERLIST         3                /* Layer list (scroll list) */
1155
 
#define DCFO_NEWLAYER          5                /* New layer (edit text) */
1156
 
#define DCFO_OMIMICDISPLAY     6                /* Output Mimics Display (check) */
1157
 
#define DCFO_OMERGEBOXES       7                /* Output Merges Boxes (check) */
1158
 
#define DCFO_ISQUAREWIRES      8                /* Input Squares Wires (check) */
1159
 
#define DCFO_OINSTANTIATETOP   9                /* Output Instantiates top (check) */
1160
 
#define DCFO_ORESOLUTION_L    10                /* Output Resolution label (stat text) */
1161
 
#define DCFO_ORESOLUTION      11                /* Output resolution (edit text) */
1162
 
#define DCFO_ORESOLUTIONMODE  12                /* Output resolution mode (popup) */
1163
 
#define DCFO_ONORMALIZECOORD  13                /* Output normalizes coordinates (check) */
1164
 
 
1165
 
void io_cifoptionsdlog(void)
1166
 
{
1167
 
        INTBIG newstate[NUMIOSTATEBITWORDS];
1168
 
        REGISTER INTBIG *curstate, oldresolution, i, itemHit, nameschanged;
1169
 
        REGISTER char **layernames, *pt;
1170
 
        char *newlang[3];
1171
 
        REGISTER VARIABLE *var, *cifvar;
1172
 
        static char *whattodisplay[] = {N_("No Resolution Check"),
1173
 
                N_("Report Resolution Errors"), N_("Show Resolution Errors")};
1174
 
 
1175
 
        if (DiaInitDialog(&io_cifoptionsdialog)) return;
1176
 
        for(i=0; i<3; i++) newlang[i] = _(whattodisplay[i]);
1177
 
        DiaSetPopup(DCFO_ORESOLUTIONMODE, 3, newlang);
1178
 
        DiaInitTextDialog(DCFO_LAYERLIST, DiaNullDlogList, DiaNullDlogItem,
1179
 
                DiaNullDlogDone, 0, SCSELMOUSE|SCREPORT);
1180
 
        layernames = (char **)emalloc(el_curtech->layercount * (sizeof (char *)),
1181
 
                el_tempcluster);
1182
 
        cifvar = getval((INTBIG)el_curtech, VTECHNOLOGY, VSTRING|VISARRAY,
1183
 
                "IO_cif_layer_names");
1184
 
        for(i=0; i<el_curtech->layercount; i++)
1185
 
        {
1186
 
                if (cifvar == NOVARIABLE || i >= getlength(cifvar)) pt = ""; else
1187
 
                        pt = ((char **)cifvar->addr)[i];
1188
 
                (void)allocstring(&layernames[i], pt, el_tempcluster);
1189
 
                (void)initinfstr();
1190
 
                (void)addstringtoinfstr(layername(el_curtech, i));
1191
 
                (void)addstringtoinfstr(" (");
1192
 
                (void)addstringtoinfstr(pt);
1193
 
                (void)addstringtoinfstr(")");
1194
 
                DiaStuffLine(DCFO_LAYERLIST, returninfstr());
1195
 
        }
1196
 
        DiaSelectLine(DCFO_LAYERLIST, 0);
1197
 
        DiaSetText(DCFO_NEWLAYER, layernames[0]);
1198
 
        curstate = io_getstatebits();
1199
 
        for(i=0; i<NUMIOSTATEBITWORDS; i++) newstate[i] = curstate[i];
1200
 
        if ((curstate[0]&CIFOUTEXACT) != 0) DiaSetControl(DCFO_OMIMICDISPLAY, 1);
1201
 
        if ((curstate[0]&CIFOUTMERGE) != 0) DiaSetControl(DCFO_OMERGEBOXES, 1);
1202
 
        if ((curstate[0]&CIFINSQUARE) != 0) DiaSetControl(DCFO_ISQUAREWIRES, 1);
1203
 
        if ((curstate[0]&CIFOUTNOTOPCALL) == 0) DiaSetControl(DCFO_OINSTANTIATETOP, 1);
1204
 
        if ((curstate[0]&CIFOUTNORMALIZE) != 0) DiaSetControl(DCFO_ONORMALIZECOORD, 1);
1205
 
        var = getval((INTBIG)el_curtech, VTECHNOLOGY, VINTEGER, "IO_cif_resolution");
1206
 
        if (var == NOVARIABLE) oldresolution = 0; else oldresolution = var->addr;
1207
 
        if (oldresolution == 0)
1208
 
        {
1209
 
                DiaSetText(DCFO_ORESOLUTION, "");
1210
 
                DiaSetPopupEntry(DCFO_ORESOLUTIONMODE, 0);
1211
 
                DiaDimItem(DCFO_ORESOLUTION_L);
1212
 
                DiaDimItem(DCFO_ORESOLUTION);
1213
 
        } else
1214
 
        {
1215
 
                DiaUnDimItem(DCFO_ORESOLUTION_L);
1216
 
                DiaUnDimItem(DCFO_ORESOLUTION);
1217
 
                DiaSetText(DCFO_ORESOLUTION, latoa(oldresolution));
1218
 
                if ((curstate[1]&CIFRESHIGH) != 0)
1219
 
                        DiaSetPopupEntry(DCFO_ORESOLUTIONMODE, 2); else
1220
 
                                DiaSetPopupEntry(DCFO_ORESOLUTIONMODE, 1);
1221
 
        }
1222
 
 
1223
 
        /* loop until done */
1224
 
        nameschanged = 0;
1225
 
        for(;;)
1226
 
        {
1227
 
                itemHit = DiaNextHit();
1228
 
                if (itemHit == CANCEL) break;
1229
 
                if (itemHit == OK)
1230
 
                {
1231
 
                        i = DiaGetPopupEntry(DCFO_ORESOLUTIONMODE);
1232
 
                        if (i != 0 && atola(DiaGetText(DCFO_ORESOLUTION)) == 0)
1233
 
                        {
1234
 
                                DiaMessageInDialog(_("Must set nonzero output resolution"));
1235
 
                                continue;
1236
 
                        }
1237
 
                        break;
1238
 
                }
1239
 
                if (itemHit == DCFO_OMIMICDISPLAY || itemHit == DCFO_OMERGEBOXES ||
1240
 
                        itemHit == DCFO_ISQUAREWIRES || itemHit == DCFO_OINSTANTIATETOP ||
1241
 
                        itemHit == DCFO_ONORMALIZECOORD)
1242
 
                {
1243
 
                        DiaSetControl(itemHit, 1 - DiaGetControl(itemHit));
1244
 
                        continue;
1245
 
                }
1246
 
                if (itemHit == DCFO_LAYERLIST)
1247
 
                {
1248
 
                        i = DiaGetCurLine(DCFO_LAYERLIST);
1249
 
                        DiaSetText(DCFO_NEWLAYER, layernames[i]);
1250
 
                        continue;
1251
 
                }
1252
 
                if (itemHit == DCFO_ORESOLUTIONMODE)
1253
 
                {
1254
 
                        i = DiaGetPopupEntry(DCFO_ORESOLUTIONMODE);
1255
 
                        if (i == 0)
1256
 
                        {
1257
 
                                DiaDimItem(DCFO_ORESOLUTION_L);
1258
 
                                DiaDimItem(DCFO_ORESOLUTION);
1259
 
                                DiaSetText(DCFO_ORESOLUTION, "");
1260
 
                        } else
1261
 
                        {
1262
 
                                DiaUnDimItem(DCFO_ORESOLUTION_L);
1263
 
                                DiaUnDimItem(DCFO_ORESOLUTION);
1264
 
                                if (atola(DiaGetText(DCFO_ORESOLUTION)) == 0)
1265
 
                                        DiaSetText(DCFO_ORESOLUTION, "1");
1266
 
                        }
1267
 
                        continue;
1268
 
                }
1269
 
                if (itemHit == DCFO_NEWLAYER)
1270
 
                {
1271
 
                        i = DiaGetCurLine(DCFO_LAYERLIST);
1272
 
                        pt = DiaGetText(DCFO_NEWLAYER);
1273
 
                        if (strcmp(pt, layernames[i]) == 0) continue;
1274
 
                        nameschanged++;
1275
 
                        (void)reallocstring(&layernames[i], pt, el_tempcluster);
1276
 
                        (void)initinfstr();
1277
 
                        (void)addstringtoinfstr(layername(el_curtech, i));
1278
 
                        (void)addstringtoinfstr(" (");
1279
 
                        (void)addstringtoinfstr(layernames[i]);
1280
 
                        (void)addstringtoinfstr(")");
1281
 
                        DiaSetScrollLine(DCFO_LAYERLIST, i, returninfstr());
1282
 
                        continue;
1283
 
                }
1284
 
        }
1285
 
 
1286
 
        if (itemHit != CANCEL)
1287
 
        {
1288
 
                if (DiaGetControl(DCFO_OMIMICDISPLAY) != 0) newstate[0] |= CIFOUTEXACT; else
1289
 
                        newstate[0] &= ~CIFOUTEXACT;
1290
 
                if (DiaGetControl(DCFO_OMERGEBOXES) != 0) newstate[0] |= CIFOUTMERGE; else
1291
 
                        newstate[0] &= ~CIFOUTMERGE;
1292
 
                if (DiaGetControl(DCFO_ISQUAREWIRES) != 0) newstate[0] |= CIFINSQUARE; else
1293
 
                        newstate[0] &= ~CIFINSQUARE;
1294
 
                if (DiaGetControl(DCFO_OINSTANTIATETOP) == 0) newstate[0] |= CIFOUTNOTOPCALL; else
1295
 
                        newstate[0] &= ~CIFOUTNOTOPCALL;
1296
 
                if (DiaGetControl(DCFO_ONORMALIZECOORD) != 0) newstate[0] |= CIFOUTNORMALIZE; else
1297
 
                        newstate[0] &= ~CIFOUTNORMALIZE;
1298
 
                if (DiaGetPopupEntry(DCFO_ORESOLUTIONMODE) == 2) newstate[1] |= CIFRESHIGH; else
1299
 
                        newstate[1] &= ~CIFRESHIGH;
1300
 
                for(i=0; i<NUMIOSTATEBITWORDS; i++) if (curstate[i] != newstate[i]) break;
1301
 
                if (i < NUMIOSTATEBITWORDS) io_setstatebits(newstate);
1302
 
                if (nameschanged != 0)
1303
 
                        setval((INTBIG)el_curtech, VTECHNOLOGY, "IO_cif_layer_names",
1304
 
                                (INTBIG)layernames, VSTRING|VISARRAY|
1305
 
                                        (el_curtech->layercount<<VLENGTHSH));
1306
 
                i = atola(DiaGetText(DCFO_ORESOLUTION));
1307
 
                if (i != oldresolution)
1308
 
                        setval((INTBIG)el_curtech, VTECHNOLOGY, "IO_cif_resolution", i, VINTEGER);
1309
 
        }
1310
 
        for(i=0; i<el_curtech->layercount; i++) efree(layernames[i]);
1311
 
        efree((char *)layernames);
1312
 
        DiaDoneDialog();
1313
 
}
1314
 
 
1315
 
#endif  /* IOCIF - at top */