$SP,"<1>",1$ $SP,"<2>",2$ $SP,"<3>",3$ $SP,"<4>",4$ $SP,"<5>",5$ $SP,"<6>",6$ #define A_EAST 0 #define A_NORTH 1 #define A_WEST 2 #define A_SOUTH 3 U0 OrthRot(I64 *_x,I64 *_y,I64 é) { nobound_switch (é&3) { case A_EAST: break; case A_NORTH: *_y=-*_y; SwapU64(_x,_y); break; case A_WEST: *_x=-*_x; *_y=-*_y; break; case A_SOUTH: *_x=-*_x; SwapU64(_x,_y); break; } } #define MAX_TERMINALS 6 #define ET_R 0 #define ET_L 1 #define ET_C 2 #define ET_NUM_TYPES 3 class ElementType { U8 *black_img,*red_img; I64 terminals; CD2I64 term[MAX_TERMINALS]; I64 min_x,max_x,min_y,max_y; }; ElementType et[ET_NUM_TYPES] = { {$IB,"<1>",1$,$IB,"<2>",2$,2,{{-12,1},{13,1},{0,0},{0,0},{0,0},{0,0}},0,0,0,0}, {$IB,"<3>",3$,$IB,"<4>",4$,2,{{-14,0},{15,0},{0,0},{0,0},{0,0},{0,0}},0,0,0,0}, {$IB,"<5>",5$,$IB,"<6>",6$,2,{{-4 ,0},{6 ,0},{0,0},{0,0},{0,0},{0,0}},0,0,0,0}, }; extern class Element; class Terminal { Element *e; I64 terminal; }; #define Df_PROCESSED 0 #define Df_JUNCTION 1 #define Df_TERMINAL 2 #define Df_TERMINAL_LEFT 3 #define Df_TERMINAL_RIGHT 4 #define Df_TERMINAL_TOP 5 #define Df_TERMINAL_BOTTOM 6 class Dot //These are points on a node { Dot *next,*last; I64 x,y,saved_x,saved_y; Element *e; U16 flags[4]; Dot *left,*right,*top,*bottom; }; class Node { Node *next,*last; I64 cnt; Terminal *terms; Dot *dot_root; } node_root; class Element { Element *next,*last; ElementType *type; I64 x,y,é,min_x,max_x,min_y,max_y; Node *nodes[MAX_TERMINALS]; } el_root; #define MD_CONNECT 0 #define MD_MOVE 1 #define MD_NUM_MODES 2 I64 mode; Element *rubber_band; I64 rubber_band_terminal,rubber_band_x,rubber_band_y; U0 DotDel(Dot *root) { if (root) { QueDel(root,TRUE); Free(root); } } U0 DotRst(Dot *root) { Dot *tempd; if (root) { Bts(root->flags,Df_PROCESSED); tempd=root->next; while (tempd!=root) { Btr(tempd->flags,Df_PROCESSED); tempd=tempd->next; } } } #define DIR_LT 0 #define DIR_CT 1 #define DIR_RT 2 #define DIR_LC 3 #define DIR_CC 4 #define DIR_RC 5 #define DIR_LB 6 #define DIR_CB 7 #define DIR_RB 8 I64 ElementSqrDist(Element *tempe,I64 x,I64 y) { I64 i,dx,dy; if (xmin_x) i=0; else if (x<=tempe->max_x) i=1; else i=2; if (y>=tempe->min_y) { if (y<=tempe->max_y) i+=3; else i+=6; } switch (i) { case DIR_LT: dx=tempe->min_x-x; dy=tempe->min_y-y; break; case DIR_CT: dx=0; dy=tempe->min_y-y; break; case DIR_RT: dx=x-tempe->max_x; dy=tempe->min_y-y; break; case DIR_LC: dx=tempe->min_x-x; dy=0; break; case DIR_CC: dx=0; dy=0; break; case DIR_RC: dx=x-tempe->max_x; dy=0; break; case DIR_LB: dx=tempe->min_x-x; dy=y-tempe->max_y; break; case DIR_CB: dx=0; dy=y-tempe->max_y; break; case DIR_RB: dx=x-tempe->max_x; dy=y-tempe->max_y; break; } return SqrI64(dx)+SqrI64(dy); } #define SPACING 10 F64 DotNetScore(Dot *root) { //higher is better F64 d,distdist1=0.1,distdist2=0.1,num=1.0,den=0.1; I64 dx,dy,nonzero_cnt=1; Element *tempe; Dot *tempd,*tempd1; if (root) { tempd=root->next; while (tempd!=root) { //Calculate clearance from elements like parallel resistors tempe=el_root.next; while (tempe!=&el_root) { if (tempd->e!=tempe) { d=Sqrt(ElementSqrDist(tempe,tempd->x,tempd->y))+0.1; if (d>SPACING) d=SPACING; num*=d; den+=d; } tempe=tempe->next; } //Calculate clearance from junctions like parallel resistors if (Bt(tempd->flags,Df_TERMINAL)) { tempd1=root->next; while (tempd1!=root) { if (tempd1!=tempd && Bt(tempd1->flags,Df_JUNCTION)) { d=Sqrt(SqrI64(tempd->x-tempd1->x)+SqrI64(tempd->y-tempd1->y))+0.1; if (d>SPACING) d=SPACING; num*=d; den+=d; } tempd1=tempd1->next; } } if (tempd1=tempd->left) { dx=SqrI64(tempd->x-tempd1->x); dy=SqrI64(tempd->y-tempd1->y); if (d=dx+dy) { distdist1+=d; nonzero_cnt++; } distdist2+=dy; } if (tempd1=tempd->right) { dx=SqrI64(tempd->x-tempd1->x); dy=SqrI64(tempd->y-tempd1->y); if (d=dx+dy) { distdist1+=d; nonzero_cnt++; } distdist2+=dy; } if (tempd1=tempd->top) { dx=SqrI64(tempd->x-tempd1->x); dy=SqrI64(tempd->y-tempd1->y); if (d=dx+dy) { distdist1+=d; nonzero_cnt++; } distdist2+=dx; } if (tempd1=tempd->bottom) { dx=SqrI64(tempd->x-tempd1->x); dy=SqrI64(tempd->y-tempd1->y); if (d=dx+dy) { distdist1+=d; nonzero_cnt++; } distdist2+=dx; } tempd=tempd->next; } } return num/(nonzero_cnt*nonzero_cnt*nonzero_cnt*distdist1*distdist2); } Bool NodeAdd(Node *tempn,Element *tempe,I64 terminal,CTask *mem_task=NULL) { I64 i; Terminal *a; for (i=0;icnt;i++) if (tempn->terms[i].e==tempe&&tempn->terms[i].terminal==terminal) return TRUE; a=MAlloc((tempn->cnt+1)*sizeof(Terminal),mem_task); if (tempn->terms) { MemCpy(a,tempn->terms,tempn->cnt*sizeof(Terminal)); Free(tempn->terms); } tempn->terms=a; i=tempn->cnt++; tempn->terms[i].e=tempe; tempn->terms[i].terminal=terminal; return FALSE; } U0 NodeDel(Node *tempn) { if (tempn) { QueRem(tempn); Free(tempn->terms); if (tempn->dot_root) DotDel(tempn->dot_root); Free(tempn); } } extern Dot *DotNew(Node *tempn,CTask *mem_task=NULL); U0 NodeReroute(Node *tempn=NULL,CTask *mem_task=NULL) { if (tempn) { DotDel(tempn->dot_root); tempn->dot_root=DotNew(tempn,mem_task); } else { tempn=node_root.next; while (tempn!=&node_root) { DotDel(tempn->dot_root); tempn->dot_root=DotNew(tempn,mem_task); tempn=tempn->next; } } } U0 ElementExtents(Element *tempe) { ElementType *tempt=tempe->type; I64 x,y; x=tempt->min_x; y=tempt->min_y; OrthRot(&x,&y,tempe->é); x+=tempe->x; y+=tempe->y; tempe->min_x=tempe->max_x=x; tempe->min_y=tempe->max_y=y; x=tempt->max_x; y=tempt->max_y; OrthRot(&x,&y,tempe->é); x+=tempe->x; y+=tempe->y; if (xmin_x) tempe->min_x=x; if (x>tempe->max_x) tempe->max_x=x; if (ymin_y) tempe->min_y=y; if (y>tempe->max_y) tempe->max_y=y; if (tempe==rubber_band) { tempe->min_x+=ipx-rubber_band_x; tempe->max_x+=ipx-rubber_band_x; tempe->min_y+=ipy-rubber_band_y; tempe->max_y+=ipy-rubber_band_y; } } U0 ElementReroute(Element *tempe,CTask *mem_task=NULL) { I64 i; ElementType *tempt; if (tempe) { tempt=tempe->type; for (i=0;iterminals;i++) if (tempe->nodes[i]) NodeReroute(tempe->nodes[i],mem_task); } } U0 ElementDel(Element *tempe,CTask *mem_task=NULL) { I64 i,cnt; Terminal *src,*dst; Node *tempn=node_root.next,*tempn1; while (tempn!=&node_root) { tempn1=tempn->next; cnt=0; dst=src=tempn->terms; for (i=0;icnt;i++) { if (src->e!=tempe) { if (dst!=src) MemCpy(dst,src,sizeof(Terminal)); cnt++; dst++; } src++; } if (tempn->cnt!=cnt) { tempn->cnt=cnt; if (!cnt) NodeDel(tempn); else if (cnt==1) { tempn->terms[0].e->nodes[tempn->terms[0].terminal]=NULL; NodeDel(tempn); } else { DotDel(tempn->dot_root); tempn->dot_root=NULL; NodeReroute(tempn,mem_task); } } tempn=tempn1; } QueRem(tempe); Free(tempe); } Node *NodeNew(CTask *mem_task=NULL) { Node *result=CAlloc(sizeof(Node),mem_task); QueIns(result,node_root.last); return result; } Node *NodeCat(Node *dst,Node *src,CTask *mem_task=NULL) { I64 i; if (!dst) dst=NodeNew(mem_task); if (src && dst!=src) { for (i=0;icnt;i++) { NodeAdd(dst,src->terms[i].e,src->terms[i].terminal,mem_task); src->terms[i].e->nodes[src->terms[i].terminal]=dst; } NodeDel(src); } return dst; } U0 TerminalXY(Element *tempe,I64 terminal,I64 *_x,I64 *_y) { ElementType *tempt=tempe->type; I64 x=tempt->term[terminal].x,y=tempt->term[terminal].y; OrthRot(&x,&y,tempe->é); if (_x) *_x=tempe->x+x; if (_y) *_y=tempe->y+y; } #define CT_NONE 0 #define CT_LEFT 1 #define CT_RIGHT 2 #define CT_TOP 3 #define CT_BOTTOM 4 I64 DotHVDecideConnect(Dot *tempd,Dot *tempd1) { I64 d; d=tempd->x-tempd1->x; if (d<0) { if (!tempd->right && !tempd1->left || tempd->right==tempd1 && tempd1->left==tempd) return CT_RIGHT; } else if (d>0) { if (!tempd->left && !tempd1->right || tempd->left==tempd1 && tempd1->right==tempd) return CT_LEFT; } d=tempd->y-tempd1->y; if (d<0) { if (!tempd->bottom && !tempd1->top || tempd->bottom==tempd1 && tempd1->top==tempd) return CT_BOTTOM; } else if (d>0) { if (!tempd->top && !tempd1->bottom || tempd->top==tempd1 && tempd->bottom==tempd) return CT_TOP; } return CT_NONE; } Bool DotHVConnect(Dot *tempd,Dot *tempd1) { switch (DotHVDecideConnect(tempd,tempd1)) { case CT_RIGHT: tempd ->right=tempd1; tempd1->left =tempd; return TRUE; case CT_LEFT: tempd ->left =tempd1; tempd1->right=tempd; return TRUE; case CT_BOTTOM: tempd ->bottom=tempd1; tempd1->top =tempd; return TRUE; case CT_TOP: tempd ->top =tempd1; tempd1->bottom=tempd; return TRUE; default: return FALSE; } } Dot *DotHVInterconnect(Dot *tempd,Dot *tempd1,CTask *mem_task=NULL) { I64 type; Dot *result=CAlloc(sizeof(Dot),mem_task); if (Bt(tempd ->flags,Df_TERMINAL_LEFT)|| Bt(tempd ->flags,Df_TERMINAL_RIGHT)) { //d horizontal type=0; if (Bt(tempd1->flags,Df_TERMINAL_TOP)|| Bt(tempd1->flags,Df_TERMINAL_BOTTOM)) {//d1 vertical if (tempd->yy && Bt(tempd1->flags,Df_TERMINAL_TOP)|| tempd->y>tempd1->y && Bt(tempd1->flags,Df_TERMINAL_BOTTOM)) type=1; } else { if (tempd->x>tempd1->x && Bt(tempd1->flags,Df_TERMINAL_LEFT)|| tempd->xx && Bt(tempd1->flags,Df_TERMINAL_RIGHT)) type=1; } } else { //d vertical type=1; if (Bt(tempd1->flags,Df_TERMINAL_LEFT)|| Bt(tempd1->flags,Df_TERMINAL_RIGHT)) { //d1 horizontal if (tempd->xx && Bt(tempd1->flags,Df_TERMINAL_LEFT)|| tempd->x>tempd1->x && Bt(tempd1->flags,Df_TERMINAL_RIGHT)) type=0; } else { if (tempd->y>tempd1->y && Bt(tempd1->flags,Df_TERMINAL_TOP)|| tempd->yy && Bt(tempd1->flags,Df_TERMINAL_BOTTOM)) type=0; } } if (type==1) { result->x=tempd1->x; result->y=tempd ->y; } else { result->x=tempd ->x; result->y=tempd1->y; } return result; } Dot *DotNearest(Dot *root,Dot *tempd,Bool just_processed) { I64 best_dd=MAX_I64,dx,dy,dd; Dot *result=NULL,*tempd1,*tempd2; if (root && tempd) { tempd1=root->next; while (tempd1!=root) { if (tempd1!=tempd && (!just_processed||Bt(tempd1->flags,Df_PROCESSED))) { dx=tempd->x-tempd1->x; dy=tempd->y-tempd1->y; dd=SqrI64(dx)+SqrI64(dy); if (0next; } } return result; } Bool DotMarkConnected(Dot *tempd) { if (tempd && !Bts(tempd->flags,Df_PROCESSED)) { DotMarkConnected(tempd->left); DotMarkConnected(tempd->right); DotMarkConnected(tempd->top); DotMarkConnected(tempd->bottom); return TRUE; } else return FALSE; } U0 DotSpacersAdd(Dot *root,CTask *mem_task=NULL) { Dot *tempd,*tempd1,*tempd2; if (root) { tempd=root->next; if (tempd!=root) { tempd2=root->last; do { if (Bt(tempd->flags,Df_TERMINAL)) { tempd1=CAlloc(sizeof(Dot),mem_task); tempd1->x=tempd->x; tempd1->y=tempd->y; tempd1->flags[0]=tempd->flags[0]; tempd1->e=tempd->e; if (Bt(tempd->flags,Df_TERMINAL_LEFT)) { tempd->right=tempd1; tempd1->left=tempd; tempd->x--; } if (Bt(tempd->flags,Df_TERMINAL_RIGHT)) { tempd->left=tempd1; tempd1->right=tempd; tempd->x++; } if (Bt(tempd->flags,Df_TERMINAL_TOP)) { tempd->bottom=tempd1; tempd1->top=tempd; tempd->y--; } if (Bt(tempd->flags,Df_TERMINAL_BOTTOM)) { tempd->top=tempd1; tempd1->bottom=tempd; tempd->y++; } tempd->flags[0]=0; tempd->e=NULL; QueIns(tempd1,root->last); } tempd=tempd->next; } while (tempd!=tempd2); } } } U0 DotAddSpace(Dot *root) { F64 score,best_score; I64 i,x,y,best_x,best_y; Dot *tempd,*tempd1; if (root) { tempd=root->next; while (tempd!=root) { tempd->saved_x=tempd->x; tempd->saved_y=tempd->y; tempd=tempd->next; } best_score=DotNetScore(root); tempd=root->next; while (tempd!=root) { if (!Bt(tempd->flags,Df_TERMINAL)) { best_x=0; best_y=0; for (i=0;i<4*SPACING;i++) { nobound_switch (i&3) { case A_EAST: x= i>>2; y=0; break; case A_NORTH: y= i>>2; x=0; break; case A_WEST: x=-i>>2; y=0; break; case A_SOUTH: y=-i>>2; x=0; break; } tempd->x=tempd->saved_x+x; tempd1=tempd->top; while (tempd1 && !Bt(tempd1->flags,Df_TERMINAL)) { tempd1->x=tempd1->saved_x+x; tempd1=tempd1->top; } tempd1=tempd->bottom; while (tempd1 && !Bt(tempd1->flags,Df_TERMINAL)) { tempd1->x=tempd1->saved_x+x; tempd1=tempd1->bottom; } tempd->y=tempd->saved_y+y; tempd1=tempd->left; while (tempd1 && !Bt(tempd1->flags,Df_TERMINAL)) { tempd1->y=tempd1->saved_y+y; tempd1=tempd1->left; } tempd1=tempd->right; while (tempd1 && !Bt(tempd1->flags,Df_TERMINAL)) { tempd1->y=tempd1->saved_y+y; tempd1=tempd1->right; } score=DotNetScore(root); if (score>best_score) { best_score=score; best_x=x; best_y=y; } } tempd->saved_x=tempd->x=tempd->saved_x+best_x; tempd1=tempd->top; while (tempd1 && !Bt(tempd1->flags,Df_TERMINAL)) { tempd1->saved_x=tempd1->x=tempd1->saved_x+best_x; tempd1=tempd1->top; } tempd1=tempd->bottom; while (tempd1 && !Bt(tempd1->flags,Df_TERMINAL)) { tempd1->saved_x=tempd1->x=tempd1->saved_x+best_x; tempd1=tempd1->bottom; } tempd->saved_y=tempd->y=tempd->saved_y+best_y; tempd1=tempd->left; while (tempd1 && !Bt(tempd1->flags,Df_TERMINAL)) { tempd1->saved_y=tempd1->y=tempd1->saved_y+best_y; tempd1=tempd1->left; } tempd1=tempd->right; while (tempd1 && !Bt(tempd1->flags,Df_TERMINAL)) { tempd1->saved_y=tempd1->y=tempd1->saved_y+best_y; tempd1=tempd1->right; } } tempd=tempd->next; } } } U0 DotJunctions(Dot *root) { I64 cnt; Dot *tempd; tempd=root->next; while (tempd!=root) { if (Bt(tempd->flags,Df_TERMINAL)) cnt=1; else cnt=0; if (tempd->left) cnt++; if (tempd->right) cnt++; if (tempd->top) cnt++; if (tempd->bottom) cnt++; BEqu(tempd->flags,Df_JUNCTION,cnt>2); tempd=tempd->next; } } Dot *DotTerminalsNew(Node *tempn,CTask *mem_task=NULL) { I64 i,min_x,max_x,min_y,max_y,dx,dy,x,y; Element *tempe; Dot *result=CAlloc(sizeof(Dot),mem_task),*tempd; QueInit(result); for (i=0;icnt;i++) if (tempe=tempn->terms[i].e) { tempd=CAlloc(sizeof(Dot),mem_task); Bts(tempd->flags,Df_TERMINAL); tempd->e=tempe; TerminalXY(tempe,tempn->terms[i].terminal,&tempd->x,&tempd->y); x=tempe->x; y=tempe->y; if (mode==MD_MOVE && tempe==rubber_band) { tempd->x+=ipx-rubber_band_x; tempd->y+=ipy-rubber_band_y; x+=ipx-rubber_band_x; y+=ipy-rubber_band_y; } min_x=AbsI64(tempd->x-tempe->min_x); max_x=AbsI64(tempd->x-tempe->max_x); if (min_xy-tempe->min_y); max_y=AbsI64(tempd->y-tempe->max_y); if (min_yx<=x) Bts(tempd->flags,Df_TERMINAL_LEFT); else Bts(tempd->flags,Df_TERMINAL_RIGHT); } else { if (tempd->y<=y) Bts(tempd->flags,Df_TERMINAL_TOP); else Bts(tempd->flags,Df_TERMINAL_BOTTOM); } QueIns(tempd,result->last); } return result; } Dot *DotNew(Node *tempn,CTask *mem_task=NULL) { I64 cnt,pass=0,last_cnt=0; Bool cont; Dot *tempd,*tempd1,*tempd2,*tempd3; Dot *result=DotTerminalsNew(tempn,mem_task); do { pass++; tempd=result->next; while (tempd!=result) { if (!Bt(tempd->flags,Df_PROCESSED)) { if (tempd1=DotNearest(result,tempd,pass>1)) { if (tempd->x==tempd1->x || tempd->y==tempd1->y) { if (tempd->x!=tempd1->x || tempd->y!=tempd1->y) { if (DotHVConnect(tempd,tempd1)) DotMarkConnected(tempd); } }else { tempd2=DotHVInterconnect(tempd,tempd1,mem_task); tempd3=result->next; while (tempd3!=result) { if (tempd2->x==tempd3->x && tempd2->y==tempd3->y) break; tempd3=tempd3->next; } if (tempd3!=result) { Free(tempd2); tempd2=tempd3; } else QueIns(tempd2,result->last); if (DotHVConnect(tempd,tempd2)) { DotMarkConnected(tempd); if (DotHVConnect(tempd2,tempd1)) DotMarkConnected(tempd1); } else DotHVConnect(tempd2,tempd1); } } } tempd=tempd->next; } tempd=result->next; while (tempd!=result) { tempd1=tempd->next; while (tempd1!=result) { if (tempd1->y==tempd->y) { if ((tempd2=tempd->left ) && tempd2->xxx) { tempd ->left =tempd1; tempd1->right=tempd ; tempd1->left =tempd2; tempd2->right=tempd1; } if ((tempd2=tempd->right ) && tempd ->xxx) { tempd2->left =tempd1; tempd1->right=tempd2; tempd1->left =tempd ; tempd ->right=tempd1; } } if (tempd1->x==tempd->x) { if ((tempd2=tempd->top ) && tempd2->yyy) { tempd ->top =tempd1; tempd1->bottom=tempd ; tempd1->top =tempd2; tempd2->bottom=tempd1; } if ((tempd2=tempd->bottom) && tempd ->yyy) { tempd2->top =tempd1; tempd1->bottom=tempd2; tempd1->top =tempd ; tempd ->bottom=tempd1; } } tempd1=tempd1->next; } tempd=tempd->next; } cont=FALSE; DotRst(result); cnt=0; tempd=result->next; if (tempd!=result) { DotMarkConnected(tempd); while (tempd!=result) { if (Bt(tempd->flags,Df_PROCESSED)) cnt++; else cont=TRUE; tempd=tempd->next; } if (last_cnt==cnt) break; last_cnt=cnt; } } while (cont); DotJunctions(result); DotSpacersAdd(result,mem_task); DotAddSpace(result); DotJunctions(result); return result; } U0 DotDraw(CDC *dc,Dot *root) { Dot *tempd,*tempd1; if (root) { tempd=root->next; while (tempd!=root) { Bts(tempd->flags,Df_PROCESSED); if ((tempd1=tempd->right) && !Bt(tempd1->flags,Df_PROCESSED)) GrLine(dc,tempd->x,tempd->y,tempd1->x,tempd1->y); if ((tempd1=tempd->left) && !Bt(tempd1->flags,Df_PROCESSED)) GrLine(dc,tempd->x,tempd->y,tempd1->x,tempd1->y); if ((tempd1=tempd->top) && !Bt(tempd1->flags,Df_PROCESSED)) GrLine(dc,tempd->x,tempd->y,tempd1->x,tempd1->y); if ((tempd1=tempd->bottom) && !Bt(tempd1->flags,Df_PROCESSED)) GrLine(dc,tempd->x,tempd->y,tempd1->x,tempd1->y); if (Bt(tempd->flags,Df_JUNCTION)) { dc->pen_width=3; GrPlot3(dc,tempd->x,tempd->y,0); dc->pen_width=1; } tempd=tempd->next; } } } U0 DrawIt(CTask *task,CDC *dc) { I64 i,x1,y1,x2,y2; U8 *img; Bool old_preempt=Preempt(OFF); Node *tempn=node_root.next; Element *tempe=el_root.next; while (tempe!=&el_root) { x1=tempe->x; y1=tempe->y; if (mode==MD_MOVE && tempe==rubber_band) { img=tempe->type->red_img; x1+=ipx-rubber_band_x; y1+=ipy-rubber_band_y; } else img=tempe->type->black_img; CSpritePlotRotZ3b(dc,x1,y1,0,img,tempe->é*pi/2); tempe=tempe->next; } while (tempn!=&node_root) { dc->color=BLUE; if (mode==MD_MOVE) for (i=0;icnt;i++) if (tempn->terms[i].e==rubber_band) { dc->color=RED; break; } DotRst(tempn->dot_root); DotDraw(dc,tempn->dot_root); tempn=tempn->next; } if (mode==MD_CONNECT && rubber_band && rubber_band_terminal>=0) { TerminalXY(rubber_band,rubber_band_terminal,&x1,&y1); x2=ipx-task->win_pixel_left-task->win_scroll_x; y2=ipy-task->win_pixel_top -task->win_scroll_y; dc->color=RED; GrLine(dc,x1,y1,x2,y2); } Preempt(old_preempt); dc->color=BLACK; GrPutS(dc,0,0,"Right Mouse Change Modes"); switch (mode) { case MD_CONNECT: GrPutS(dc,20,FONT_HEIGHT,"Connect Components"); break; case MD_MOVE: GrPutS(dc,20,FONT_HEIGHT,"Move Components"); break; } } U0 RubberReset() { rubber_band=NULL; rubber_band_terminal=-1; rubber_band_x=0; rubber_band_y=0; } U0 Init() { I64 i; ElementType *tempt; for (i=0;iblack_img,&tempt->min_x,&tempt->max_x,&tempt->min_y,&tempt->max_y); } mode=MD_CONNECT; RubberReset; QueInit(&el_root); QueInit(&node_root); } U0 CleanUp() { Element *tempe=el_root.next,*tempe1; Node *tempn=node_root.next,*tempn1; while (tempe!=&el_root) { tempe1=tempe->next; QueRem(tempe); Free(tempe); tempe=tempe1; } while (tempn!=&node_root) { tempn1=tempn->next; NodeDel(tempn); tempn=tempn1; } } Element *ElementNew(I64 t,CTask *mem_task=NULL) { Element *tempe=CAlloc(sizeof(Element),mem_task); tempe->type=&et[t]; tempe->x=ipx-Fs->win_pixel_left-Fs->win_scroll_x; tempe->y=ipy-Fs->win_pixel_top -Fs->win_scroll_y; QueIns(tempe,el_root.last); ElementExtents(tempe); return tempe; } Element *ElementFind(I64 x,I64 y,I64 *_terminal) { I64 i,x2,y2,best_dd=MAX_I64,dd; Element *result=NULL,*tempe=el_root.next; if (_terminal) *_terminal=0; while (tempe!=&el_root) { for (i=0;itype->terminals;i++) { TerminalXY(tempe,i,&x2,&y2); dd=SqrI64(x-x2)+SqrI64(y-y2); if (ddnext; } return result; } U0 Circuit() { I64 p1,p2,terminal1=-1,terminal2=-1; Element *tempe1=NULL,*tempe2=NULL; Node *tempn; PopUpOk( "This is not useful.\n" "It just lets you draw\n" "a circuit.\n"); SettingsPush; //See $LK,"SettingsPush","MN:SettingsPush"$ Preempt(OFF); WordStat; WinMax; MenuPush( "File {" " New(,CH_NEW_LINE);" " Abort(,CH_SHIFT_ESC);" " Exit(,CH_ESC);" "}" "Edit {" " Rotate(,CH_SPACE);" " DelElement(,,SC_DELETE);" "}" "Mode {" " Connect(,0,SC_F2);" " Move(,0,SC_F3);" "}" "PlaceElement {" " Resistor(,'r');" " Inductor(,'l');" " Capacitor(,'c');" "}" ); Init; DocCursor; DocClear; Fs->draw_it=&DrawIt; Fs->win_inhibit=WIF_ALL-WIF_BORDER-WIF_MENU-WIF_GRAB_SCROLL; try { while (TRUE) { switch (GetMsg(&p1,&p2,1<win_pixel_left-Fs->win_scroll_x, ipy-Fs->win_pixel_top -Fs->win_scroll_y,&terminal1); ElementDel(tempe1,Fs); tempe1=NULL; terminal1=-1; tempe2=NULL; terminal2=-1; RubberReset; break; } break; case CH_NEW_LINE: CleanUp; Init; break; case CH_ESC: case CH_SHIFT_ESC: goto cs_done; case 'r': tempe1=ElementNew(ET_R); terminal1=-1; break; case 'l': tempe1=ElementNew(ET_L); terminal1=-1; break; case 'c': tempe1=ElementNew(ET_C); terminal1=-1; break; case CH_SPACE: if (tempe1) { tempe1->é=(tempe1->é+1)&3; ElementExtents(tempe1); ElementReroute(tempe1,Fs); } break; } break; case MSG_IP_MOVE: if (tempe1) { ElementExtents(tempe1); ElementReroute(tempe1,Fs); } break; case MSG_IP_L_DOWN: tempe1=ElementFind(p1,p2,&terminal1); rubber_band=tempe1; rubber_band_terminal=terminal1; rubber_band_x=ipx; rubber_band_y=ipy; break; case MSG_IP_L_UP: rubber_band=NULL; switch (mode) { case MD_CONNECT: if (tempe1 && terminal1>=0) { if ((tempe2=ElementFind(p1,p2,&terminal2)) && (tempe2!=tempe1 || terminal2!=terminal1)) { if (!(tempn=tempe1->nodes[terminal1]) && !(tempn=tempe2->nodes[terminal2])) tempn=NodeNew; NodeAdd(tempn,tempe1,terminal1); NodeAdd(tempn,tempe2,terminal2); if (tempe1->nodes[terminal1]) NodeCat(tempn,tempe1->nodes[terminal1]); tempe1->nodes[terminal1]=tempn; if (tempe2->nodes[terminal2]) NodeCat(tempn,tempe2->nodes[terminal2]); tempe2->nodes[terminal2]=tempn; NodeReroute(tempn,Fs); } } break; case MD_MOVE: if (tempe1 && terminal1>=0) { tempe1->x+=ipx-rubber_band_x; tempe1->y+=ipy-rubber_band_y; ElementExtents(tempe1); ElementReroute(tempe1,Fs); } break; } tempe1=NULL; terminal1=-1; tempe2=NULL; terminal2=-1; RubberReset; break; case MSG_IP_R_DOWN: if (mode+1==MD_NUM_MODES) mode=0; else mode++; tempe1=NULL; terminal1=-1; tempe2=NULL; terminal2=-1; RubberReset; break; } } cs_done: } catch CatchAll; SettingsPop; CleanUp; MenuPop; } Circuit; œöÿÿÿùÿÿÿþÿÿÿùÿÿÿþÿÿÿüÿÿÿüÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿýÿÿÿ þÿÿÿöÿÿÿôÿÿÿ  òÿÿÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿXüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúÿÿÿÿÿÿÿÿÿÿÿúÿÿÿœöÿÿÿùÿÿÿþÿÿÿùÿÿÿþÿÿÿüÿÿÿüÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿýÿÿÿ þÿÿÿöÿÿÿôÿÿÿ  òÿÿÿýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿXüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿúÿÿÿÿÿÿÿÿÿÿÿúÿÿÿ