home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / modelers / linkedit / linkedit.lha / link-edit / LinkEdit / Link / link_public.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-03-13  |  17.7 KB  |  815 lines

  1. #include <stdio.h>
  2. #include <X11/Xlib.h>
  3. #include "link_types.h"
  4. #include "link_global.h"
  5.  
  6. LinkList *LinkCreateNewLink(status)
  7. VOID *status;
  8.  
  9. {
  10.   LinkStatus *gnrc;
  11.   LinkList *lnk;
  12.  
  13.   gnrc = (LinkStatus *) status;
  14.   lnk = &(gnrc->link);
  15.   while(lnk->next != NULL) lnk = lnk->next;
  16.   lnk->next = (LinkList *) malloc(sizeof(LinkList));
  17.   if((lnk = lnk->next) == NULL) {
  18.      fprintf(stderr,"Warning:  unable to allocate new link.\n");
  19.      return(NULL);
  20.     }
  21.  
  22.   lnk->next = NULL;
  23.   lnk->point.next = NULL;
  24.   lnk->visible = LINK_YES;
  25.   lnk->closed = LINK_NO;
  26.   lnk->num = 0;
  27.   gnrc->current_link = lnk;
  28.   gnrc->num++;
  29.   return(lnk);
  30. }
  31.  
  32. LinkModeNone(status)
  33.  
  34. VOID *status;  
  35. {
  36.   LinkStatus *gnrc;
  37.   gnrc = (LinkStatus *) status;
  38.   gnrc->choice[0] = LINK_NO_CHOICE;
  39. }
  40.  
  41. LinkModeAddPoint(status)
  42.  
  43. VOID *status;  
  44. {
  45.   LinkStatus *gnrc;
  46.   gnrc = (LinkStatus *) status;
  47.   gnrc->choice[0] = LINK_ADD_POINT;
  48.   LinkPrintMessage(gnrc,"Click to add point.");
  49. }
  50.  
  51. LinkModeDeletePoint(status)
  52.  
  53. VOID *status;  
  54. {
  55.   LinkStatus *gnrc;
  56.   gnrc = (LinkStatus *) status;
  57.   gnrc->choice[0] = LINK_DELETE_POINT;
  58.   LinkPrintMessage(gnrc,"Click to delete point.");
  59. }
  60.  
  61. LinkModeMovePoint(status)
  62.  
  63. VOID *status;  
  64. {
  65.   LinkStatus *gnrc;
  66.   gnrc = (LinkStatus *) status;
  67.   gnrc->choice[0] = LINK_MOVE_POINT;
  68.   LinkPrintMessage(gnrc,"Click and drag to move point.");
  69. }
  70.  
  71. LinkModeSelectLink(status)
  72. VOID *status;  
  73. {
  74.   LinkStatus *gnrc;
  75.   gnrc = (LinkStatus *) status;
  76.   gnrc->choice[0] = LINK_SELECT_LINK;
  77.   LinkPrintMessage(gnrc,"Click to select strand.");
  78. }
  79.  
  80. LinkModeHideLink(status)
  81.  
  82. VOID *status;  
  83. {
  84.   LinkStatus *gnrc;
  85.   gnrc = (LinkStatus *) status;
  86.   gnrc->choice[0] = LINK_HIDE_LINK;
  87. }
  88.  
  89. LinkModeTranslateLink(status)
  90.  
  91. VOID *status;  
  92. {
  93.   LinkStatus *gnrc;
  94.   gnrc = (LinkStatus *) status;
  95.   gnrc->choice[0] = LINK_TRANSLATE_LINK;
  96.   LinkPrintMessage(gnrc,"Click and drag to translate strand.");
  97. }
  98.  
  99. LinkModeRotateLink(status)
  100.  
  101. VOID *status;  
  102. {
  103.   LinkStatus *gnrc;
  104.   gnrc = (LinkStatus *) status;
  105.   gnrc->choice[0] = LINK_ROTATE_LINK;
  106.   LinkPrintMessage(gnrc,"Sorry, rotating is not yet implemented.");
  107. }
  108.  
  109. LinkModeScaleLink(status)
  110.  
  111. VOID *status;  
  112. {
  113.   LinkStatus *gnrc;
  114.   gnrc = (LinkStatus *) status;
  115.   gnrc->choice[0] = LINK_SCALE_LINK;
  116.   LinkPrintMessage(gnrc,"Sorry, scaling is not yet implemented.");
  117. }
  118.  
  119. LinkModeShiftView(status)
  120.  
  121. VOID *status;  
  122. {
  123.   LinkStatus *gnrc;
  124.   gnrc = (LinkStatus *) status;
  125.   gnrc->choice[0] = LINK_SHIFT_VIEW;
  126.   LinkPrintMessage(gnrc,"Click and drag to shift view.");
  127. }
  128.  
  129. LinkModeFlipCrossing(status)
  130.  
  131. VOID *status;  
  132. {
  133.   LinkStatus *gnrc;
  134.   gnrc = (LinkStatus *) status;
  135.   gnrc->choice[0] = LINK_FLIP_CROSSING;
  136.   LinkPrintMessage(gnrc,"Click to flip crossing.");
  137. }
  138.  
  139. LinkModeZoomView(status)
  140.  
  141. VOID *status;  
  142. {
  143.   LinkStatus *gnrc;
  144.   gnrc = (LinkStatus *) status;
  145.   gnrc->choice[0] = LINK_ZOOM_VIEW;
  146.   LinkPrintMessage(gnrc,"Click and drag to zoom view.");
  147. }
  148.  
  149. LinkModeJoinLinks(status)
  150.  
  151. VOID *status;  
  152. {
  153.   LinkStatus *gnrc;
  154.   gnrc = (LinkStatus *) status;
  155.   gnrc->choice[0] = LINK_JOIN_SELECT_HEAD;
  156.   LinkPrintMessage(gnrc,"Select end of first strand.");
  157. }
  158.  
  159. LinkModeReverseArrows(status)
  160.  
  161. VOID *status;  
  162. {
  163.   LinkStatus *gnrc;
  164.   gnrc = (LinkStatus *) status;
  165.   gnrc->choice[0] = LINK_REVERSE_ARROWS;
  166.   LinkPrintMessage(gnrc,"Select strand to reverse.");
  167. }
  168.  
  169. LinkModeCloseStrand(status)
  170. VOID *status;  
  171. {
  172.   LinkStatus *gnrc;
  173.   gnrc = (LinkStatus *) status;
  174.   gnrc->choice[0] = LINK_CLOSE_LINK;
  175.   LinkPrintMessage(gnrc,"Select strand to close.");
  176. }
  177.  
  178. LinkModeOpenStrand(status)
  179. VOID *status;  
  180. {
  181.   LinkStatus *gnrc;
  182.   gnrc = (LinkStatus *) status;
  183.   gnrc->choice[0] = LINK_OPEN_LINK;
  184.   LinkPrintMessage(gnrc,"Select strand to open.");
  185. }
  186.  
  187. LinkModeDeleteStrand(status)
  188. VOID *status;  
  189. {
  190.   LinkStatus *gnrc;
  191.   gnrc = (LinkStatus *) status;
  192.   gnrc->choice[0] = LINK_DELETE_LINK;
  193.   LinkPrintMessage(gnrc,"Select strand to delete.");
  194. }
  195.  
  196.  
  197. LinkShowXRuler(status)
  198.  
  199. VOID *status;
  200. {
  201.   LinkStatus *gnrc;
  202.   gnrc = (LinkStatus *) status;
  203.   gnrc->xruler = LINK_SHOW;
  204. }
  205.  
  206.  
  207. LinkShowYRuler(status)
  208.  
  209. VOID *status;
  210. {
  211.   LinkStatus *gnrc;
  212.   gnrc = (LinkStatus *) status;
  213.   gnrc->yruler = LINK_SHOW;
  214. }
  215.  
  216.  
  217. LinkHideXRuler(status)
  218.  
  219. VOID *status;
  220. {
  221.   LinkStatus *gnrc;
  222.   gnrc = (LinkStatus *) status;
  223.   gnrc->xruler = LINK_HIDE;
  224. }
  225.  
  226.  
  227. LinkHideYRuler(status)
  228.  
  229. VOID *status;
  230. {
  231.   LinkStatus *gnrc;
  232.   gnrc = (LinkStatus *) status;
  233.   gnrc->yruler = LINK_HIDE;
  234. }
  235.  
  236. LinkPublicReDraw(status)
  237. VOID *status;  
  238. {
  239.   LinkStatus *gnrc;
  240.   gnrc = (LinkStatus *) status;
  241.   XClearWindow(dpy,gnrc->TopWindow);
  242.   ReDrawLinkTopWindow(gnrc);
  243. }
  244.  
  245. LinkPublicClear(status)
  246. VOID *status;
  247. {
  248.   LinkStatus *gnrc;
  249.   gnrc = (LinkStatus *) status;
  250.   XClearWindow(dpy,gnrc->TopWindow);
  251.   LinkClearData(gnrc);
  252. }
  253.  
  254. LinkOpenCurrentLink(status)
  255. VOID *status;
  256. {
  257.   LinkStatus *gnrc;
  258.   LinkList *lnk;
  259.   LinkPointList *pnt;
  260.  
  261.   gnrc = (LinkStatus *) status;
  262.   lnk = gnrc->current_link;
  263.   if(lnk == NULL) {
  264.      LinkPrintMessage(gnrc,"No currently selected link.");
  265.      return;
  266.     }
  267.   if(!lnk->closed) {
  268.      LinkPrintMessage(gnrc,"Link is already open.");
  269.      return;
  270.     }
  271.   lnk->closed = 0;
  272.  
  273.   /* find last point */
  274.   pnt = &(lnk->point);
  275.   if(pnt->next == NULL) {
  276.      LinkPrintMessage(gnrc,"Link is empty!");
  277.      return;
  278.     }
  279.   while(pnt->next != NULL) pnt = pnt->next;
  280.  
  281.   LinkFreeEdgeCrossings(gnrc,lnk,pnt);
  282.   XClearWindow(dpy,gnrc->TopWindow);
  283.   ReDrawLinkTopWindow(gnrc);
  284.  
  285. }
  286.  
  287. LinkCloseCurrentLink(status)
  288. VOID *status;
  289. {
  290.   LinkStatus *gnrc;
  291.   LinkList *lnk;
  292.   LinkPointList *pnt;
  293.  
  294.   gnrc = (LinkStatus *) status;
  295.   lnk = gnrc->current_link;
  296.   if(lnk == NULL) {
  297.      LinkPrintMessage(gnrc,"No currently selected strand.");
  298.      return;
  299.     }
  300.   if(lnk->closed) {
  301.      LinkPrintMessage(gnrc,"Strand is already closed.");
  302.      return;
  303.     }
  304.   if(lnk->num < 3) {
  305.      LinkPrintMessage(gnrc,"Too few points to close strand!");
  306.      return;
  307.     }
  308.   /* find last point */
  309.   pnt = &(lnk->point);
  310.   if(pnt->next == NULL) {
  311.      LinkPrintMessage(gnrc,"Link is empty!");
  312.      return;
  313.     }
  314.   lnk->closed = 1;
  315.   while(pnt->next != NULL) pnt = pnt->next;
  316.   LinkComputeEdgeCrossings(gnrc,lnk,pnt);
  317.   XClearWindow(dpy,gnrc->TopWindow);
  318.   ReDrawLinkTopWindow(gnrc);
  319. }
  320.  
  321. LinkPublicPrintMessage(status,mssg)
  322.  
  323. VOID *status;
  324. char *mssg;
  325.  
  326. {
  327.   LinkStatus *gnrc;
  328.  
  329.   gnrc = (LinkStatus *) status;
  330.   LinkPrintMessage(gnrc,mssg);
  331. }
  332.  
  333. LinkPublicUrgentWindowDialogue(status,prmpt,rtrn)
  334.  
  335. VOID *status;
  336. char *prmpt,*rtrn;
  337.  
  338. {
  339.   LinkStatus *gnrc;
  340.   int num;
  341.  
  342.   gnrc = (LinkStatus *) status;
  343.   num = LinkUrgentWindowDialogue(gnrc,prmpt,rtrn);
  344.   return(num);
  345. }
  346.  
  347. LinkShowAll(status)
  348.  
  349. VOID *status;
  350. {
  351.   LinkStatus *gnrc;
  352.   LinkList *lnk;
  353.  
  354.   gnrc = (LinkStatus *) status;
  355.   lnk = gnrc->link.next;
  356.   while(lnk != NULL) {
  357.      lnk->visible = LINK_SHOW;
  358.      lnk = lnk->next;
  359.     }
  360.   XClearWindow(dpy,gnrc->TopWindow);
  361.   ReDrawLinkTopWindow(gnrc);
  362. }
  363.  
  364. LinkDeleteCurrentSelection(status)
  365. VOID *status;
  366. {
  367.   LinkStatus *gnrc;
  368.  
  369.   gnrc = (LinkStatus *) status;
  370.   LinkDeleteLink(gnrc,gnrc->current_link);
  371. }
  372.  
  373. LinkPublicDeleteAll(status)
  374. VOID *status;
  375. {
  376.   LinkStatus *gnrc;
  377.  
  378.   gnrc = (LinkStatus *) status;
  379.   LinkDeleteAll(gnrc);
  380. }
  381.  
  382. LinkSetAxes(status,set)
  383. VOID *status; int set;
  384. {
  385.   LinkStatus *gnrc;
  386.   gnrc = (LinkStatus *) status;
  387.   gnrc->axes = set;
  388. }
  389.  
  390. LinkSetArrows(status,set)
  391. VOID *status; int set;
  392. {
  393.   LinkStatus *gnrc;
  394.   gnrc = (LinkStatus *) status;
  395.   gnrc->arrows = set;
  396. }
  397.  
  398. LinkSetVertices(status,set)
  399. VOID *status; int set;
  400. {
  401.   LinkStatus *gnrc;
  402.   gnrc = (LinkStatus *) status;
  403.   gnrc->vertices = set;
  404. }
  405.  
  406. LinkSetRulers(status,set)
  407. VOID *status; int set;
  408. {
  409.   LinkStatus *gnrc;
  410.   gnrc = (LinkStatus *) status;
  411.   gnrc->xruler = set;
  412.   gnrc->yruler = set;
  413. }
  414.  
  415. LinkSaveAll(status,name)
  416. VOID *status; char *name;
  417. /* returns 0 if successful */
  418. {
  419.   char strng[160];
  420.   FILE *fp;
  421.   LinkList *lnk;
  422.   LinkPointList *pnt;
  423.   LinkCrossingList *crssng;
  424.   int lnk_id,pnt_id,num_crssng;
  425.  
  426.   LinkStatus *gnrc;
  427.   gnrc = (LinkStatus *) status;
  428.  
  429.   fp = fopen(name,"w");
  430.   if(fp == NULL) {
  431.     sprintf(strng,"Cannot open file %s\n",name);
  432.     LinkPrintMessage(gnrc,strng);
  433.     return(-1);
  434.    }
  435.   fprintf(fp,"LINK_PROJECTION\n");
  436.   
  437.   /* Save strand data */
  438.   lnk = gnrc->link.next;
  439.   lnk_id = 0;
  440.   while(lnk != NULL) {
  441.      fprintf(fp," Strand %d\n",lnk_id);
  442.      LinkPrintLink(gnrc,fp,lnk);
  443.      /* Set id's while we're at it...*/
  444.      lnk->id = lnk_id;
  445.      lnk_id++;
  446.      lnk = lnk->next;
  447.     }
  448.  
  449.   /* set link_id for each point */
  450.   lnk = gnrc->link.next;
  451.   while(lnk != NULL) {
  452.      lnk_id = lnk->id;
  453.      pnt = lnk->point.next;
  454.      pnt_id = 0;
  455.      while(pnt != NULL) {
  456.         pnt->link_id = lnk_id;
  457.         pnt->point_id = pnt_id;
  458.         pnt_id++;
  459.         pnt = pnt->next;
  460.        }
  461.      lnk = lnk->next;
  462.     }
  463.  
  464.   /* Save crossing data */
  465.   fprintf(fp,"# crossing format: \n");
  466.   fprintf(fp,"#    UpLinkID EdgeID   DownLinkID EdgeID   UpParam DownParam\n");
  467.  
  468.   /* Count number of over crossings */
  469.   lnk = gnrc->link.next;
  470.   num_crssng = 0;
  471.   while(lnk != NULL) {
  472.      pnt = lnk->point.next;
  473.      while(pnt != NULL) {
  474.         crssng = pnt->crossing.next;
  475.         while(crssng != NULL) {
  476.            if(crssng->z > 0.0) { /* Over crossing */
  477.               num_crssng++;
  478.              }
  479.            crssng = crssng->next;
  480.           }
  481.         pnt = pnt->next;
  482.        }
  483.      lnk = lnk->next;
  484.     }
  485.   fprintf(fp," Crossings %d\n",num_crssng);
  486.   /* save only over crossings- under crossing implicit */
  487.   lnk = gnrc->link.next;
  488.   while(lnk != NULL) {
  489.      pnt = lnk->point.next;
  490.      while(pnt != NULL) {
  491.         crssng = pnt->crossing.next;
  492.         while(crssng != NULL) {
  493.            if(crssng->z > 0.0) { /* Over crossing */
  494.               fprintf(fp,"   %d %d   %d %d   %.4lf  %.4lf\n",
  495.                            lnk->id, pnt->point_id,
  496.                            crssng->partner->link_id,crssng->partner->point_id,
  497.                            crssng->param,crssng->crossing->param);
  498.              }
  499.            crssng = crssng->next;
  500.           }
  501.         pnt = pnt->next;
  502.        }
  503.      lnk = lnk->next;
  504.     }
  505.   fprintf(fp," End \n\n");
  506.   fclose(fp);
  507.   return(0);
  508. }
  509.  
  510. LinkSaveThreeD(status,name)
  511. VOID *status; char *name;
  512. /* returns 0 if successful */
  513. {
  514.   char strng[160];
  515.   FILE *fp;
  516.   LinkList *lnk;
  517.   LinkPointList *pnt;
  518.   LinkCrossingList *crssng;
  519.   int num_links,num_points;
  520.  
  521.   LinkStatus *gnrc;
  522.   gnrc = (LinkStatus *) status;
  523.  
  524.   fp = fopen(name,"w");
  525.   if(fp == NULL) {
  526.     sprintf(strng,"Cannot open file %s\n",name);
  527.     LinkPrintMessage(gnrc,strng);
  528.     return(-1);
  529.    }
  530.   fprintf(fp,"LINK\n");
  531.   /* Count Number of links */
  532.   num_links = 0;
  533.   lnk = gnrc->link.next;
  534.   while(lnk != NULL){
  535.      if(lnk->point.next != NULL) { /* Print only nonempty links */
  536.         num_links++;
  537.        }
  538.      lnk = lnk->next;
  539.     }
  540.    fprintf(fp,"%d\n",num_links);
  541.  
  542.   /* Count and print number of points for each strand */
  543.   lnk = gnrc->link.next;
  544.   while(lnk != NULL){
  545.      if((pnt = lnk->point.next) != NULL) {  /* Non-empty links only */
  546.         num_points=0;
  547.         while(pnt != NULL) {
  548.            num_points++;
  549.            crssng = pnt->crossing.next;
  550.            while(crssng != NULL) {
  551.               num_points++;
  552.               crssng = crssng->next;
  553.              }
  554.            pnt = pnt->next;
  555.           }
  556.         fprintf(fp,"%d\n",num_points);
  557.        }
  558.      lnk = lnk->next;
  559.     }
  560.  
  561.   /* Print out starnd data */
  562.   lnk = gnrc->link.next;
  563.   while(lnk != NULL){
  564.      if(lnk->point.next != NULL) { /* Only non-empty strands */
  565.         LinkPrintStrand3D(gnrc,fp,lnk);
  566.         fprintf(fp,"\n");
  567.        }
  568.      lnk = lnk->next;
  569.     }
  570.   fclose(fp);
  571.   return(0);
  572. }
  573.  
  574. LinkSavePS(status,name)
  575. VOID *status; char *name;
  576. /* returns 0 if successful */
  577. {
  578.   char strng[160];
  579.   FILE *fp;
  580.   LinkList *lnk;
  581.  
  582.   LinkStatus *gnrc;
  583.   gnrc = (LinkStatus *) status;
  584.  
  585.   fp = fopen(name,"w");
  586.   if(fp == NULL) {
  587.     sprintf(strng,"Cannot open file %s\n",name);
  588.     LinkPrintMessage(gnrc,strng);
  589.     return(-1);
  590.    }
  591.   /* Print PS header */
  592.  
  593.   fprintf(fp,"%%!PS-Adobe-1.0\n");
  594. /*
  595.   fprintf(fp,"%%%%BoundingBox: %d %d %d %d\n",dcxmin,dcymin,dcxmax,dcymax);
  596. */
  597.  
  598.   fprintf(fp,"%%%%Pages: 1\n");
  599.   fprintf(fp,"%%%%EndComments\n\n");
  600.  
  601.  
  602.   /* 2.835 = Postscript units per mm */
  603.   fprintf(fp,"%lf %lf scale\n",2.835,2.835);
  604.  
  605.   fprintf(fp,"0 setlinewidth\n");
  606.   fprintf(fp,"1 setlinecap\n");
  607.  
  608.   fprintf(fp,"/vec { moveto lineto stroke } def\n");
  609.   fprintf(fp,"%%%%Endprolog\n\n");
  610.   fprintf(fp,"%%%%Page: 1\n\n");
  611.  
  612.   lnk = gnrc->link.next;
  613.   while(lnk != NULL){
  614.      LinkPrintStrandPS(gnrc,fp,lnk);
  615.      lnk = lnk->next;
  616.     }
  617.  
  618.   fprintf(fp,"\nshowpage\n");
  619.   fprintf(fp,"%%%%Trailer\n");
  620.  
  621.   fclose(fp);
  622.   return(0);
  623. }
  624.  
  625. LinkGetFile(status,name)
  626. VOID *status; char *name;
  627. /* returns 0 if successful */
  628. {
  629.   char strng[40];
  630.   int done,ch,num_links,num_crssng;
  631.   FILE *fp;
  632.   LinkList link,*lnk,*tmp_lnk;
  633.   LinkPointList *pnt;
  634.   int i,lnk_id,pnt_id;
  635.   LinkStatus *gnrc;
  636.  
  637.   gnrc = (LinkStatus *) status;
  638.  
  639.   if((fp = fopen(name,"r")) == NULL) {
  640.      sprintf(strng,"Could not open %s.",name);
  641.      LinkPrintMessage(gnrc,strng);
  642.      return(-1);
  643.     }
  644.  
  645.   lnk = &link;
  646.   lnk->next = NULL;
  647.   num_links = 0;
  648.  
  649.   while(fscanf(fp,"%s",strng) == 1) {
  650.      if(strcmp(strng,"Strand") == 0) {
  651.         lnk->next = (LinkList *) malloc(sizeof(LinkList));
  652.         lnk = lnk->next; lnk->next = NULL;
  653.         lnk->point.next = NULL;
  654.         lnk->num = 0; lnk->visible = LINK_YES;
  655.         fscanf(fp,"%d",&(lnk->id));
  656.         num_links++;
  657.         if(LinkReadStrand(gnrc,fp,lnk) != 0) {
  658.            sprintf(strng,"Error reading %s.",name);
  659.            LinkPrintMessage(gnrc,strng);
  660.            fclose(fp);
  661.            return(-1);
  662.           }
  663.         continue;
  664.        }
  665.      if(strng[0] == '#') { /* Read till end of line */
  666.         ch = 'a';
  667.         while(ch != '\n' && ch != '\r') {
  668.            ch = fgetc(fp);
  669.            if(ch == EOF) {
  670.               LinkPrintMessage(gnrc,"Error reading link file comment.");
  671.               fclose(fp);
  672.               return(-1);
  673.              }
  674.           }
  675.        }
  676.      if(strcmp(strng,"Crossings") == 0) {
  677.         int up_lnk_id, dwn_lnk_id, up_pnt_id, dwn_pnt_id;
  678.         LinkList *up_lnk,*dwn_lnk,**lnk_tbl;
  679.         LinkPointList point,*up_pnt,*dwn_pnt;
  680.         LinkCrossingList crossing;
  681.         double up_param,dwn_param;
  682.         double x0,y0,x1,y1;
  683.  
  684.         fscanf(fp,"%d",&num_crssng);
  685.  
  686.         /* make table of lnk pointers by id */
  687.         if(num_links < 1) continue;
  688.         lnk_tbl = (LinkList **) malloc(num_links*sizeof(LinkList *));
  689.         tmp_lnk = link.next;
  690.         while(tmp_lnk != NULL) {
  691.            lnk_tbl[tmp_lnk->id] = tmp_lnk; 
  692.            tmp_lnk = tmp_lnk->next;
  693.           }
  694.  
  695.         /* Read crossings */
  696.         for(i=0;i<num_crssng;++i) {
  697.            fscanf(fp,"%d %d %d %d %lf %lf\n",&up_lnk_id,&up_pnt_id,
  698.                                        &dwn_lnk_id,&dwn_pnt_id,
  699.                                        &up_param,&dwn_param);
  700.            up_lnk = lnk_tbl[up_lnk_id];
  701.            dwn_lnk = lnk_tbl[dwn_lnk_id];
  702.  
  703.         /* find points corresponding to point id's */
  704.         /* NOTE: point id's assumed correct from ReadStrand */
  705.            up_pnt = up_lnk->point.next;
  706.            while(up_pnt != NULL && up_pnt->point_id !=  up_pnt_id)
  707.                up_pnt = up_pnt->next;
  708.            dwn_pnt = dwn_lnk->point.next;
  709.            while(dwn_pnt != NULL && dwn_pnt->point_id !=  dwn_pnt_id)
  710.                dwn_pnt = dwn_pnt->next;
  711.  
  712.            if(up_pnt == NULL || dwn_pnt == NULL) {
  713.               LinkPrintMessage(gnrc,"Invalid point id in crossing.");
  714.               fclose(fp);
  715.               return(-1);
  716.              }
  717.  
  718.            x0 = up_pnt->x; y0 = up_pnt->y;
  719.            if(up_pnt->next != NULL) 
  720.               { x1 = up_pnt->next->x; y1 = up_pnt->next->y;}
  721.            else if(up_lnk->closed) 
  722.                    {x1=up_lnk->point.next->x; y1=up_lnk->point.next->y;}
  723.            point.x = crossing.x = (1.0-up_param)*x0 + up_param*x1;
  724.            point.y = crossing.y = (1.0-up_param)*y0 + up_param*y1;
  725.            LinkComputePointDeviceCoords(gnrc,&point);
  726.            crossing.dcx = point.dcx; crossing.dcy = point.dcy;
  727.  
  728.            LinkInsertCrossing(gnrc,up_lnk,up_pnt,dwn_lnk,dwn_pnt,
  729.                                 &crossing,up_param,dwn_param);
  730.           }
  731.         free(lnk_tbl);
  732.         continue;
  733.        }
  734.     }
  735.  
  736.   
  737.   /* Compute crossings between new and old links */
  738.   lnk = link.next;
  739.   while(lnk != NULL) {
  740.      pnt = lnk->point.next;
  741.      while(pnt != NULL) {
  742.         LinkComputeEdgeCrossings(gnrc,lnk,pnt);
  743.         pnt = pnt->next;
  744.        }
  745.      lnk = lnk->next;
  746.     }
  747.  
  748.   /* Find last link of existing links */
  749.   /* Join the new links with the old */
  750.   lnk = &(gnrc->link);
  751.   while(lnk->next != NULL) lnk = lnk->next;
  752.   lnk->next = link.next;
  753.  
  754.   return(0);
  755. }
  756.  
  757. LinkCenterView(status)
  758. VOID *status; 
  759. {
  760.   LinkStatus *gnrc;
  761.   LinkList *lnk;
  762.   LinkPointList *pnt;
  763.   int dcxmin,dcxmax,dcymin,dcymax;
  764.   int dx,dy;
  765.   double xfactor,yfactor;
  766.  
  767.   gnrc = (LinkStatus *) status;
  768.  
  769.   /* Compute dc bounding box */
  770.   lnk = gnrc->link.next;
  771.   /* find first lnk with non empty point list */
  772.   while(lnk != NULL && lnk->point.next == NULL) lnk = lnk->next;
  773.   if(lnk == NULL) return;
  774.  
  775.   pnt = lnk->point.next;
  776.   dcxmin = pnt->dcx - 1;  dcxmax = pnt->dcx + 1;
  777.   dcymin = pnt->dcy - 1;  dcymax = pnt->dcy + 1;
  778.   while(lnk != NULL) {
  779.      if(!lnk->visible) { lnk = lnk->next; continue;}
  780.      pnt = lnk->point.next;
  781.      while(pnt != NULL) {
  782.          if(pnt->dcx < dcxmin) dcxmin = pnt->dcx;
  783.          else if(pnt->dcx > dcxmax) dcxmax = pnt->dcx;
  784.          if(pnt->dcy < dcymin) dcymin = pnt->dcy;
  785.          else if(pnt->dcy > dcymax) dcymax = pnt->dcy;
  786.          pnt = pnt->next;
  787.         }
  788.      lnk = lnk->next;
  789.     }
  790.  
  791.   /* Put center of bounding box in center of screen */
  792.  
  793.   dx = gnrc->width/2  - (dcxmax + dcxmin)/2;
  794.   dy = gnrc->height/2 - (dcymax + dcymin)/2;
  795.   gnrc->origin.dcx += dx; gnrc->origin.dcy += dy;
  796.  
  797.   /* Adjust scale so bbox takes up at most 1/2 screen in x or y direction */
  798.   /* Do not change aspect ratio */
  799.  
  800.   xfactor = 0.5 * (double) (gnrc->width) / (double) (dcxmax-dcxmin);
  801.   yfactor = 0.5 * (double) (gnrc->height) / (double) (dcymax-dcymin);
  802.   if(xfactor < yfactor) {
  803.      gnrc->xscale *= xfactor; gnrc->yscale *= xfactor;
  804.     }
  805.   else {
  806.      gnrc->xscale *= yfactor; gnrc->yscale *= yfactor;
  807.     }
  808.   LinkComputeDeviceCoords(gnrc);
  809.  
  810.   XClearWindow(dpy,gnrc->TopWindow);
  811.   ReDrawLinkTopWindow(gnrc);
  812. }
  813.  
  814.  
  815.