static WORD gr_wait(GRECT *po, GRECT *poff) { register WORD have2box; register WORD down; have2box = !rc_equal(&gl_rzero, poff); /* draw/erase old */ gsx_moff(); gr_draw(have2box, po, poff); gsx_mon(); /* wait for change */ down = gr_stilldn(TRUE, xrat, yrat, 1, 1); /* draw/erase old */ gsx_moff(); gr_draw(have2box, po, poff); gsx_mon(); /* return exit event */ return(down); }
/* returns 0 on succes */ static int proc_short(PinType *pin, PadType *pad, int ignore) { find_callback_t old_cb; Coord x, y; short_conn_t *n, **lut_by_oid, **lut_by_gid, *next; int gids; gr_t *g; void *S, *T; int *solution; int i, maxedges; int bad_gr = 0; if (!TEST_FLAG (ENABLEMINCUTFLAG, PCB)) return bad_gr; if (!Settings.EnableMincut) return bad_gr; /* only one should be set, but one must be set */ assert((pin != NULL) || (pad != NULL)); assert((pin == NULL) || (pad == NULL)); if (pin != NULL) { debprintf("short on pin!\n"); SET_FLAG (WARNFLAG, pin); x = pin->X; y = pin->Y; } else if (pad != NULL) { debprintf("short on pad!\n"); SET_FLAG (WARNFLAG, pad); if (TEST_FLAG (EDGE2FLAG, pad)) { x = pad->Point2.X; y = pad->Point2.Y; } else { x = pad->Point1.X; y = pad->Point1.Y; } } /* run only if net is not ignored */ if (ignore) return 0; short_conns = NULL; num_short_conns = 0; short_conns_maxid = 0; /* perform a search using MINCUTFLAG, calling back proc_short_cb() with the connections */ old_cb = find_callback; find_callback = proc_short_cb; SaveFindFlag(MINCUTFLAG); LookupConnection (x, y, false, 1, MINCUTFLAG); debprintf("- alloced for %d\n", (short_conns_maxid+1)); lut_by_oid = calloc(sizeof(short_conn_t *), (short_conns_maxid+1)); lut_by_gid = calloc(sizeof(short_conn_t *), (num_short_conns+3)); g = gr_alloc(num_short_conns+2); g->node2name = calloc(sizeof(char *), (num_short_conns+2)); /* conn 0 is S and conn 1 is T and set up lookup arrays */ for(n = short_conns, gids=2; n != NULL; n = n->next, gids++) { char *s, *typ; ElementType *parent; n->gid = gids; debprintf(" {%d} found %d %d/%p type %d from %d\n", n->gid, n->to_type, n->to->ID, n->to, n->type, n->from_id); lut_by_oid[n->to->ID] = n; lut_by_gid[n->gid] = n; s = malloc(256); parent = NULL; switch(n->to_type) { case PIN_TYPE: typ = "pin"; parent = ((PinType *)(n->to))->Element; break; case VIA_TYPE: typ = "via"; parent = ((PinType *)(n->to))->Element; break; case PAD_TYPE: typ = "pad"; parent = ((PadType *)(n->to))->Element; break; case LINE_TYPE: typ = "line"; break; default: typ="other"; break; } if (parent != NULL) { TextType *name; name = &parent->Name[1]; if ((name->TextString == NULL) || (*name->TextString == '\0')) sprintf(s, "%s #%d \\nof #%d", typ, n->to->ID, parent->ID); else sprintf(s, "%s #%d \\nof %s", typ, n->to->ID, name->TextString); } else sprintf(s, "%s #%d", typ, n->to->ID); g->node2name[n->gid] = s; } g->node2name[0] = strdup("S"); g->node2name[1] = strdup("T"); /* calculate how many edges each node has and the max edge count */ maxedges = 0; for(n = short_conns; n != NULL; n = n->next) { short_conn_t *from; n->edges++; if (n->edges > maxedges) maxedges = n->edges; if (n->from_id >= 0) { from = lut_by_oid[n->from_id]; if (from == NULL) { /* no from means broken graph (multiple components) */ if (n->from_id >= 2) { /* ID 0 and 1 are start/stop, there won't be from for them */ fprintf(stderr, "rats_mincut.c error: graph has multiple components, bug in find.c (n->from_id=%d)!\n", n->from_id); bad_gr = 1; } continue; } from->edges++; if (from->edges > maxedges) maxedges = from->edges; } } S = NULL; T = NULL; for(n = short_conns; n != NULL; n = n->next) { short_conn_t *from; void *spare; spare = NULL; if (n->to_type == PIN_TYPE) spare = ((PinType *)n->to)->Spare; if (n->to_type == PAD_TYPE) spare = ((PadType *)n->to)->Spare; if (spare != NULL) { void *net = &(((LibraryMenuTypePtr)spare)->Name[2]); debprintf(" net=%s\n", net); if (S == NULL) { debprintf(" -> became S\n"); S = net; } else if ((T == NULL) && (net != S)) { debprintf(" -> became T\n"); T = net; } if (net == S) gr_add_(g, n->gid, 0, 100000); else if (net == T) gr_add_(g, n->gid, 1, 100000); } /* if we have a from object, look it up and make a connection between the two gids */ if (n->from_id >= 0) { int weight; short_conn_t *from = lut_by_oid[n->from_id]; from = lut_by_oid[n->from_id]; /* weight: 1 for connections we can break, large value for connections we shall not break */ if ((n->type == FCT_COPPER) || (n->type == FCT_START)) { /* connection to a pin/pad is slightly stronger than the strongest obj-obj conn; obj-obj conns are weaker at junctions where many objects connect */ if ((n->from_type == PIN_TYPE) || (n->from_type == PAD_TYPE) || (n->to_type == PIN_TYPE) || (n->to_type == PAD_TYPE)) weight = maxedges*2 + 2; else weight = maxedges*2 - n->edges - from->edges + 1; } else weight = 10000; if (from != NULL) { gr_add_(g, n->gid, from->gid, weight); debprintf(" CONN %d %d\n", n->gid, from->gid); } } } /*#define MINCUT_DRAW*/ #ifdef MINCUT_DRAW { static int drw = 0; char gfn[256]; drw++; sprintf(gfn, "A_%d_a", drw); debprintf("gfn=%s\n", gfn); gr_draw(g, gfn, "png"); } #endif if (!bad_gr) { solution = solve(g); if (solution != NULL) { debprintf("Would cut:\n"); for(i = 0; solution[i] != -1; i++) { short_conn_t *s; debprintf("%d:", i); s = lut_by_gid[solution[i]]; debprintf("%d %p", solution[i], s); if (s != NULL) { SET_FLAG (WARNFLAG, s->to); debprintf(" -> %d", s->to->ID); } debprintf("\n"); } free(solution); } else { fprintf(stderr, "mincut didn't find a solution, falling back to the old warn\n"); bad_gr=1; } } free(lut_by_oid); free(lut_by_gid); for(n = short_conns; n != NULL; n = next) { next = n->next; free(n); } ResetFoundLinesAndPolygons(false); ResetFoundPinsViasAndPads(false); RestoreFindFlag(); find_callback = old_cb; return bad_gr; }