#include "defs.h" /* * clean all wires */ cleanall() { REG DL p; REG DL w; REG DL pindl; STRING pin; pindl=nil(DL); w=nil(DL); p=succ('M', dstart); while(1) { switch(p->type) { case 'Z': return; case 'w': cleanwire(p); if(pindl && dln(w)->name[0]=='$'){ STRING t=pindl->tag; while(*t++); if(*++t){ if(newname(w, 'p', t)) p=w; } } w=p; pindl=nil(DL); case 'c': cleanit(p); break; case 'p': if(w==nil(DL) || another(w, 'p', p)){ delete(p); continue; } pin=p->tag; while(*pin++); if(any(*pin, "<>")){ pindl=p; } break; } p=succa(p); } } DL cleanit(h) DL h; { if(h->type==succa(h)->type) { delete(h); return(h); } else return(succ(h->type, h)); } /* * remove redundancies in the list of points that * constitute a connected series of lines. * ensure that there are not line segments that overlap. * * 'w' entries consist of a set of 'e' wire segments * The first 'e' entry (if any) has the START flag set * corresponding to pen down. The last has END set. * */ #define succw(x) dlw(succa(dl(x))) #define nextw(t,x) dlw(nexta(t,dl(x))) DL cleanwire(h) DL h; { chkhd(h, "wBL"); if( (h->flag&DIRTY) == 0) return(h); while(cleaning(h)); return(h); } LOC cleaning(h) DL h; { REG DLW p, q, r; STRING pin; INT dirty; dirty = 0; r = nil(DLW); p = dlw(h); while(p=nextw(h->type,p)) { switch(p->type) { case 'e': break; default: continue; } p->flag &= ~(MARKT); if (r == nil(DLW)) p->flag |= START; if ((q = p+1)->type != 'e' || q->flag&START) p->flag |= END; if(p->flag&END) r = nil(DLW); else r = p; /* remove succesive identical points */ while(!(p->flag&END) && xysame(dl(p), dl(q=p+1))){ p->flag |= q->flag; delete(dl(q)); dirty++; } if(((p->flag & (START|END)) == 0) && between(p-1,p,p+1)) /* MARKT points in the middle of a straight segment */ p->flag |= MARKT; } p = succw(h); while(p->type != h->type) { if(p->type != 'e') { p = succw(p); continue; } if (h->type == 'w') { q=p; while(q=nextw(h->type,q)) { if( (q->type != 'e') || (q->styl != p->styl) ) continue; if( xysame(dl(p), dl(q))){ /* remove MARKT if there is another point */ p->flag &= ~MARKT; q->flag &= ~MARKT; continue; } if( !(q->flag & END) && !xysame(dl(p), dl(r=q+1)) && between(q,p,r)){ /* insert a middle point */ newdlw(AFTER, dl(q), 'e', 0, dl(p), q->styl); p->flag &= ~MARKT; dirty++; continue; } if( !(p->flag & END) && !xysame(dl(q), dl(r=p+1)) && between(p,q,r)){ /* insert a middle point */ newdlw(AFTER, dl(p), 'e', 0, dl(q), p->styl); q++; dirty++; q->flag &= ~MARKT; } } } if((p->flag & MARKT) || ((p->flag & (START|END)) == (START|END))) { delete(dl(p)); dirty++; } else p = succw(p); } /* scan third time */ p = succw(h); while(p->type != h->type) { if(p->type != 'e') goto nextp; q=p; while(q=nextw(h->type,q)) { if( (q->type != 'e') || !xysame(dl(p), dl(q)) || (q->styl != p->styl) ) continue; if((p->flag & (START|END)) && (q->flag & (START|END))){ for(r = p; !(r->flag & END); r++ ); if(q != r){ /* if q is not the END point at or after p */ concatn(p,q); dirty++; goto samep; } } if(!(p->flag & END)) { if(!(q->flag & START) && xysame(dl(p+1), dl(r=q-1))) { if((q->flag |= START) & END) { delete(dl(q)); dirty++; } if((r->flag |= END) & START) { delete(dl(r)); dirty++; } goto samep; } if(!(q->flag&END) && xysame(dl(p+1), dl(r=q+1))){ if((r->flag |= START) & END) { delete(dl(r)); dirty++; } if((q->flag |= END) & START) { delete(dl(q)); dirty++; } goto samep; } } } nextp: p = succw(p); samep: ; } return(dirty); } LOC concatn(p,q) REG DLW p, q; { INT qf,pf; qf = q->flag; pf = p->flag; p->flag &= ~(START | END); do{ if(pf & END) p++; shiftseg(p,q); if(qf & START) q++; copy(dl(q), dl(p)); p->flag &= ~(START | END); } while( !(q->flag & (START | END))); p->flag |=(pf & (START|END)); delete(dl(q)); } LOC shiftseg(p, q) REG DLW p; DLW q; { REG DLW from, to; from=q; to=q+1; do *--to = *--from; while(from > p); }