~ubuntu-branches/ubuntu/hardy/xcircuit/hardy

« back to all changes in this revision

Viewing changes to functions.c

  • Committer: Bazaar Package Importer
  • Author(s): Aanjhan Ranganathan
  • Date: 2006-04-18 23:51:39 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060418235139-s49pkhwdzxvsxm5k
Tags: 3.4.21-0ubuntu1
New upstream release

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
#include <stdlib.h>
12
12
#include <string.h>
13
13
#include <math.h>
 
14
#include <limits.h>
14
15
 
 
16
#ifndef _MSC_VER
15
17
#include <X11/Intrinsic.h>
16
18
#include <X11/StringDefs.h>
 
19
#endif
17
20
 
18
21
/*-------------------------------------------------------------------------*/
19
22
/* Local includes                                                          */
291
294
/* Find closest point of a polygon to the cursor                              */
292
295
/*----------------------------------------------------------------------------*/
293
296
 
294
 
short closepoint(polyptr curpoly, XPoint *cursloc)
 
297
short closepointdistance(polyptr curpoly, XPoint *cursloc, short *mindist)
295
298
{
296
 
   short curdist, mindist;
 
299
   short curdist;
297
300
   XPoint *curpt, *savept; 
298
301
 
299
302
   curpt = savept = curpoly->points;
300
 
   mindist = wirelength(curpt, cursloc);
 
303
   *mindist = wirelength(curpt, cursloc);
301
304
   while (++curpt < curpoly->points + curpoly->number) {
302
305
      curdist = wirelength(curpt, cursloc);
303
 
      if (curdist < mindist) {
304
 
         mindist = curdist;
 
306
      if (curdist < *mindist) {
 
307
         *mindist = curdist;
305
308
         savept = curpt;
306
309
      }
307
310
   }
309
312
}
310
313
 
311
314
/*----------------------------------------------------------------------------*/
 
315
/* Find closest point of a polygon to the cursor                              */
 
316
/*----------------------------------------------------------------------------*/
 
317
 
 
318
short closepoint(polyptr curpoly, XPoint *cursloc)
 
319
{
 
320
   short mindist;
 
321
   return closepointdistance(curpoly, cursloc, &mindist);
 
322
}
 
323
 
 
324
/*----------------------------------------------------------------------------*/
 
325
/* Find the distance to the closest point of a polygon to the cursor          */
 
326
/*----------------------------------------------------------------------------*/
 
327
 
 
328
short closedistance(polyptr curpoly, XPoint *cursloc)
 
329
{
 
330
   short mindist;
 
331
   closepointdistance(curpoly, cursloc, &mindist);
 
332
   return mindist;
 
333
}
 
334
 
 
335
/*----------------------------------------------------------------------------*/
312
336
/* Coordinate system transformations                                          */
313
337
/*----------------------------------------------------------------------------*/
314
338
 
403
427
 
404
428
/*------------------------------------------------------------------------*/
405
429
 
406
 
short UTopTransScale(float length)
 
430
float UTopTransScale(float length)
407
431
{
408
 
   /* 0.5 gives nearent int but unfortunately gives odd results. . .*/
409
 
  
410
 
   return (short)(length * UTopScale() + 0.45);
 
432
   return (float)(length * UTopScale());
411
433
}
412
434
 
413
435
/*----------------------------------------------------------------------*/
421
443
   u_int   nullui;
422
444
   XPoint newpos;
423
445
 
 
446
#ifdef TCL_WRAPPER
 
447
   /* Don't use areastruct.areawin;  if called from inside an object    */
 
448
   /* (e.g., "here" in a Tcl expression), areastruct.areawin will be    */
 
449
   /* an off-screen pixmap, and cause a crash.                          */
 
450
#ifndef _MSC_VER
 
451
   XQueryPointer(dpy, Tk_WindowId(areastruct.area), &nullwin, &nullwin,
 
452
        &nullint, &nullint, &xpos, &ypos, &nullui);
 
453
#else
 
454
   XQueryPointer_TkW32(dpy, Tk_WindowId(areastruct.area), &nullwin, &nullwin,
 
455
        &nullint, &nullint, &xpos, &ypos, &nullui);
 
456
#endif
 
457
#else
424
458
   XQueryPointer(dpy, areastruct.areawin, &nullwin, &nullwin, &nullint,
425
459
        &nullint, &xpos, &ypos, &nullui);
 
460
#endif
426
461
 
427
462
   newpos.x = xpos;
428
463
   newpos.y = ypos;
568
603
   tmpb = yscale * sin(drot);
569
604
   tmpd = -scale * sin(drot);
570
605
   tmpe = yscale * cos(drot);
571
 
   
 
606
 
572
607
   mata = ctm->a * tmpa + ctm->d * tmpb;
573
608
   matb = ctm->b * tmpa + ctm->e * tmpb;
574
609
   matc = ctm->c * tmpa + ctm->f * tmpb + position.x;
695
730
void UTransformbyCTM(Matrix *ctm, XPoint *ipoints, XPoint *points, short number)
696
731
{
697
732
   pointlist current, ptptr = points;
 
733
   float fx, fy;
698
734
   short tmpx;
699
735
 
700
736
   for (current = ipoints; current < ipoints + number; current++, ptptr++) {
701
 
      tmpx = (short)(ctm->a * (float)current->x + ctm->b * (float)current->y
702
 
                 + ctm->c);
703
 
      ptptr->y = (short)(ctm->d * (float)current->x + ctm->e * (float)current->y
704
 
                 + ctm->f);
705
 
      ptptr->x = tmpx;
 
737
      fx = ctm->a * (float)current->x + ctm->b * (float)current->y + ctm->c;
 
738
      fy = ctm->d * (float)current->x + ctm->e * (float)current->y + ctm->f;
 
739
        
 
740
      ptptr->x = (fx >= 0) ? (short)(fx + 0.5) : (short)(fx - 0.5);
 
741
      ptptr->y = (fy >= 0) ? (short)(fy + 0.5) : (short)(fy - 0.5);
706
742
   }
707
743
}
708
744
  
715
751
{
716
752
   fpointlist current;
717
753
   pointlist new = points;
 
754
   float fx, fy;
718
755
 
719
756
   for (current = fpoints; current < fpoints + number; current++, new++) {
720
 
      new->x = (short)(ctm->a * current->x + ctm->b * current->y + ctm->c);
721
 
      new->y = (short)(ctm->d * current->x + ctm->e * current->y + ctm->f);
 
757
      fx = ctm->a * current->x + ctm->b * current->y + ctm->c;
 
758
      fy = ctm->d * current->x + ctm->e * current->y + ctm->f;
 
759
      new->x = (fx >= 0) ? (short)(fx + 0.5) : (short)(fx - 0.5);
 
760
      new->y = (fy >= 0) ? (short)(fy + 0.5) : (short)(fy - 0.5);
722
761
   }
723
762
}
724
763
 
811
850
void calcextents(genericptr *bboxgen, short *llx, short *lly, 
812
851
        short *urx, short *ury)
813
852
{
814
 
   switch ((*bboxgen)->type) {
 
853
   switch (ELEMENTTYPE(*bboxgen)) {
815
854
      case(POLYGON): {
816
855
         pointlist bboxpts;
817
856
         for (bboxpts = TOPOLY(bboxgen)->points; bboxpts < TOPOLY(bboxgen)->points
849
888
/* Calculate the bounding box of an object instance                     */
850
889
/*----------------------------------------------------------------------*/
851
890
 
852
 
void objinstbbox(objinstptr obbox, XPoint *npoints)
 
891
void objinstbbox(objinstptr obbox, XPoint *npoints, Boolean expand)
853
892
{
854
893
   XPoint points[4];
 
894
   int extend = (expand) ? 4 : 0;
855
895
 
856
 
   points[0].x = points[1].x = obbox->bbox.lowerleft.x;
857
 
   points[1].y = points[2].y = obbox->bbox.lowerleft.y + obbox->bbox.height;
858
 
   points[2].x = points[3].x = obbox->bbox.lowerleft.x + obbox->bbox.width;
859
 
   points[0].y = points[3].y = obbox->bbox.lowerleft.y;
 
896
   points[0].x = points[1].x = obbox->bbox.lowerleft.x - extend;
 
897
   points[1].y = points[2].y = obbox->bbox.lowerleft.y + obbox->bbox.height
 
898
                + extend;
 
899
   points[2].x = points[3].x = obbox->bbox.lowerleft.x + obbox->bbox.width
 
900
                + extend;
 
901
   points[0].y = points[3].y = obbox->bbox.lowerleft.y - extend;
860
902
 
861
903
   UTransformPoints(points, npoints, 4, obbox->position,
862
904
                 obbox->scale, obbox->rotation); 
883
925
                + tmpext.descent;
884
926
   points[1].y = points[2].y = points[0].y + tmpext.ascent - tmpext.descent;
885
927
 
886
 
#ifdef SCHEMA
887
928
   /* separate bounding box for pinlabels and infolabels */
888
929
 
889
930
   if (labox->pin)
890
931
      for (j = 0; j < 4; j++)
891
932
         pinadjust(labox->justify, &points[j].x, &points[j].y, 1);
892
 
#endif
893
933
 
894
934
   UTransformPoints(points, npoints, 4, labox->position,
895
935
                labox->scale, labox->rotation); 
896
936
}
897
937
 
 
938
/*----------------------------------------------------------------------*/
 
939
/* Calculate the bounding box of a graphic image                        */
 
940
/*----------------------------------------------------------------------*/
 
941
 
 
942
void graphicbbox(graphicptr gp, XPoint *npoints)
 
943
{
 
944
   XPoint points[4];
 
945
   int hw = gp->source->width >> 1;
 
946
   int hh = gp->source->height >> 1;
 
947
 
 
948
   points[1].x = points[2].x = hw;
 
949
   points[0].x = points[3].x = -hw;
 
950
 
 
951
   points[0].y = points[1].y = -hh;
 
952
   points[2].y = points[3].y = hh;
 
953
 
 
954
   UTransformPoints(points, npoints, 4, gp->position,
 
955
                gp->scale, gp->rotation); 
 
956
}
 
957
 
898
958
/*--------------------------------------------------------------*/
899
959
/* Wrapper for single call to calcbboxsingle() in the netlister */
900
960
/*--------------------------------------------------------------*/
921
981
   /* For each screen element, compute the extents and revise bounding  */
922
982
   /* box points, if necessary.                                         */
923
983
 
924
 
   switch((*bboxgen)->type) {
 
984
   switch(ELEMENTTYPE(*bboxgen)) {
925
985
 
926
 
      case(OBJECT):
927
 
         objinstbbox(TOOBJINST(bboxgen), npoints);
 
986
      case(OBJINST):
 
987
         objinstbbox(TOOBJINST(bboxgen), npoints, False);
928
988
 
929
989
         for (j = 0; j < 4; j++) {
930
990
            bboxcalc(npoints[j].x, llx, urx);
933
993
         break;
934
994
 
935
995
      case(LABEL):
936
 
         {
937
 
#ifdef SCHEMA
938
 
            /* because a pin is offset from its position point, include */
939
 
            /* that point in the bounding box.                          */
940
 
 
941
 
            if (TOLABEL(bboxgen)->pin) {
942
 
               bboxcalc(TOLABEL(bboxgen)->position.x, llx, urx);
943
 
               bboxcalc(TOLABEL(bboxgen)->position.y, lly, ury);
944
 
            }
945
 
#endif
946
 
            labelbbox(TOLABEL(bboxgen), npoints, thisinst);
947
 
 
948
 
            for (j = 0; j < 4; j++) {
949
 
               bboxcalc(npoints[j].x, llx, urx);
950
 
               bboxcalc(npoints[j].y, lly, ury);
951
 
            }
952
 
         } break;
 
996
         /* because a pin is offset from its position point, include */
 
997
         /* that point in the bounding box.                             */
 
998
 
 
999
         if (TOLABEL(bboxgen)->pin) {
 
1000
            bboxcalc(TOLABEL(bboxgen)->position.x, llx, urx);
 
1001
            bboxcalc(TOLABEL(bboxgen)->position.y, lly, ury);
 
1002
         }
 
1003
         labelbbox(TOLABEL(bboxgen), npoints, thisinst);
 
1004
 
 
1005
         for (j = 0; j < 4; j++) {
 
1006
            bboxcalc(npoints[j].x, llx, urx);
 
1007
            bboxcalc(npoints[j].y, lly, ury);
 
1008
         }
 
1009
         break;
 
1010
 
 
1011
      case(GRAPHIC):
 
1012
         graphicbbox(TOGRAPHIC(bboxgen), npoints);
 
1013
         for (j = 0; j < 4; j++) {
 
1014
            bboxcalc(npoints[j].x, llx, urx);
 
1015
            bboxcalc(npoints[j].y, lly, ury);
 
1016
         }
 
1017
         break;
953
1018
 
954
1019
      case(PATH): {
955
1020
         genericptr *pathc;
990
1055
 
991
1056
   for (i = 0; i < pageobj->parts; i++) {
992
1057
      pelem = pageobj->plist + i;
993
 
      if ((*pelem)->type == OBJECT) {
 
1058
      if (IS_OBJINST(*pelem)) {
994
1059
         if ((TOOBJINST(pelem))->thisobject == thisobject)
995
1060
            return i;
996
1061
         else if ((j = find_object((TOOBJINST(pelem))->thisobject, thisobject)) >= 0)
1033
1098
   }
1034
1099
}
1035
1100
 
1036
 
#ifdef SCHEMA
1037
1101
/*--------------------------------------------------------------*/
1038
1102
/* Free memory for the schematic bounding box                   */
1039
1103
/*--------------------------------------------------------------*/
1045
1109
      thisinst->schembbox = NULL;
1046
1110
   }
1047
1111
}
1048
 
#endif
1049
1112
 
1050
1113
/*--------------------------------------------------------------*/
1051
1114
/* Calculate the bounding box for an object instance.  Use the  */
1061
1124
   genericptr *gelem;
1062
1125
   short llx, lly, urx, ury;
1063
1126
 
1064
 
#ifdef SCHEMA
1065
1127
   short pllx, plly, purx, pury;
1066
1128
   Boolean hasschembbox = FALSE;
1067
 
#endif 
1068
1129
 
1069
1130
   if (thisinst == NULL) return;
1070
1131
 
1075
1136
   urx = llx + thisobj->bbox.width;
1076
1137
   ury = lly + thisobj->bbox.height;
1077
1138
 
1078
 
#ifdef SCHEMA
1079
1139
   pllx = plly = 32767;
1080
1140
   purx = pury = -32768;
1081
 
#endif
1082
1141
 
1083
1142
   for (gelem = thisobj->plist; gelem < thisobj->plist + thisobj->parts;
1084
1143
                gelem++) {
1085
 
#ifdef SCHEMA
1086
1144
      /* pins which do not appear outside of the object */
1087
1145
      /* contribute to the objects "schembbox".         */
1088
1146
 
1089
 
      if ((*gelem)->type == LABEL) {
 
1147
      if (IS_LABEL(*gelem)) {
1090
1148
         labelptr btext = TOLABEL(gelem);
1091
1149
         if (btext->pin && !(btext->justify & PINVISIBLE)) {
1092
1150
            hasschembbox = TRUE;
1094
1152
            continue;
1095
1153
         }
1096
1154
      }
1097
 
#endif
1098
1155
 
1099
1156
      if (has_param(*gelem))
1100
1157
         calcbboxsingle(gelem, thisinst, &llx, &lly, &urx, &ury);
1105
1162
   thisinst->bbox.width = urx - llx;
1106
1163
   thisinst->bbox.height = ury - lly;
1107
1164
 
1108
 
#ifdef SCHEMA
1109
1165
   if (hasschembbox) {
1110
1166
      if (thisinst->schembbox == NULL)
1111
1167
         thisinst->schembbox = (BBox *)malloc(sizeof(BBox));
1117
1173
   }
1118
1174
   else
1119
1175
      invalidateschembbox(thisinst);
1120
 
#endif
1121
 
 
1122
1176
}
1123
1177
 
1124
1178
/*--------------------------------------------------------------*/
1130
1184
/* takes the default value.                                     */
1131
1185
/*--------------------------------------------------------------*/
1132
1186
 
1133
 
void updateinstparam(objectptr bobj, int mode)
 
1187
void updateinstparam(objectptr bobj)
1134
1188
{
1135
1189
   short i, j;
1136
1190
   objectptr pageobj;
1137
1191
 
1138
 
   /* this is a modified version of updatepagebounds()  */
1139
 
   /* mode == 0:  change bounds on pagelib and the page */
1140
 
   /* containing this object *instance*                 */
1141
 
 
1142
 
   if (mode == 0) {
1143
 
      /* pick up calling object and instance from the edit stack */
1144
 
      objinstptr pinst = areastruct.stack->thisinst;
1145
 
 
1146
 
      pageobj = pinst->thisobject;
1147
 
 
1148
 
      for (j = 0; j < pageobj->parts; j++)
1149
 
         if (*(pageobj->plist + j) == (genericptr)pinst) break;
1150
 
      if (j == pageobj->parts) {
1151
 
         Fprintf(stderr, "Error: Calling page does not contain expected objinst!\n");
1152
 
         return;
1153
 
      }
1154
 
      calcbboxvalues(pinst, (genericptr *)(pageobj->plist + j));
1155
 
      for (i = 0; i < xobjs.pages; i++) {
1156
 
         if (xobjs.pagelist[i]->pageinst != NULL) {
1157
 
            if (xobjs.pagelist[i]->pageinst->thisobject == pageobj) {
1158
 
               updatepagelib(PAGELIB, i);
1159
 
               break;
1160
 
            }
1161
 
         }
1162
 
      }
1163
 
      if (i == xobjs.pages)
1164
 
         Fprintf(stderr, "Error: Calling page not found!\n");
1165
 
   }
1166
 
 
1167
 
   /* mode == 1:  change bounds on pagelib and all pages        */
1168
 
   /*   containing this *object* if and only if the object      */
1169
 
   /*   instance takes the default value.  Also update the      */
1170
 
   /*   library page.                                           */
1171
 
 
1172
 
   else {
1173
 
      for (i = 0; i < xobjs.pages; i++)
1174
 
         if (xobjs.pagelist[i]->pageinst != NULL) {
1175
 
            pageobj = xobjs.pagelist[i]->pageinst->thisobject;
1176
 
            if ((j = find_object(pageobj, topobject)) >= 0) {
1177
 
 
1178
 
               /* Really, we'd like to recalculate the bounding box only if the */
1179
 
               /* parameter value is the default value which was just changed.  */
1180
 
               /* However, then any non-default values may contain the wrong    */
1181
 
               /* substitutions.                                                */
1182
 
 
1183
 
               objinstptr cinst = TOOBJINST(pageobj->plist + j);
1184
 
               if (cinst->thisobject->num_params == 0) {
1185
 
                  calcbboxvalues(xobjs.pagelist[i]->pageinst, pageobj->plist + j);
1186
 
                  updatepagelib(PAGELIB, i);
1187
 
               }
1188
 
            }
1189
 
         }
1190
 
 
1191
 
      for (i = 0; i < xobjs.numlibs; i++)
1192
 
         if (object_in_library(i, topobject))
1193
 
            composelib(i + LIBRARY);
1194
 
   }
 
1192
   /* change bounds on pagelib and all pages                    */
 
1193
   /* containing this *object* if and only if the object        */
 
1194
   /* instance takes the default value.  Also update the        */
 
1195
   /* library page.                                             */
 
1196
 
 
1197
   for (i = 0; i < xobjs.pages; i++)
 
1198
      if (xobjs.pagelist[i]->pageinst != NULL) {
 
1199
         pageobj = xobjs.pagelist[i]->pageinst->thisobject;
 
1200
         if ((j = find_object(pageobj, topobject)) >= 0) {
 
1201
 
 
1202
            /* Really, we'd like to recalculate the bounding box only if the */
 
1203
            /* parameter value is the default value which was just changed.     */
 
1204
            /* However, then any non-default values may contain the wrong       */
 
1205
            /* substitutions.                                           */
 
1206
 
 
1207
            objinstptr cinst = TOOBJINST(pageobj->plist + j);
 
1208
            if (cinst->thisobject->params == NULL) {
 
1209
               calcbboxvalues(xobjs.pagelist[i]->pageinst, pageobj->plist + j);
 
1210
               updatepagelib(PAGELIB, i);
 
1211
            }
 
1212
         }
 
1213
      }
 
1214
 
 
1215
   for (i = 0; i < xobjs.numlibs; i++)
 
1216
      if (object_in_library(i, topobject))
 
1217
         composelib(i + LIBRARY);
1195
1218
}
1196
1219
 
1197
1220
/*--------------------------------------------------------------*/
1263
1286
      if (newelement != NULL) bboxgen = newelement;
1264
1287
 
1265
1288
      if ((thisobj->params == NULL) || (!has_param(*bboxgen))) {
1266
 
#ifdef SCHEMA
1267
1289
         /* pins which do not appear outside of the object      */
1268
1290
         /* are ignored now---will be computed per instance.    */
1269
1291
 
1270
 
         if ((*bboxgen)->type == LABEL) {
 
1292
         if (IS_LABEL(*bboxgen)) {
1271
1293
            labelptr btext = TOLABEL(bboxgen);
1272
1294
            if (btext->pin && !(btext->justify & PINVISIBLE)) {
1273
1295
               goto nextgen;
1274
1296
            }
1275
1297
         }
1276
 
#endif
1277
1298
         calcbboxsingle(bboxgen, thisinst, &llx, &lly, &urx, &ury);
1278
1299
      }
1279
1300
nextgen:
1301
1322
      }
1302
1323
   }
1303
1324
 
1304
 
   /* set the new bounding box */
 
1325
   /* Set the new bounding box.  In pathological cases, such as a page  */
 
1326
   /* with only pin labels, the bounds may not have been changed from   */
 
1327
   /* their initial values.  If so, then don't touch the bounding box.  */
1305
1328
 
1306
 
   thisobj->bbox.lowerleft.x = llx;
1307
 
   thisobj->bbox.lowerleft.y = lly;
1308
 
   thisobj->bbox.width = urx - llx;
1309
 
   thisobj->bbox.height = ury - lly;
 
1329
   if ((llx < urx) && (lly < ury)) {
 
1330
      thisobj->bbox.lowerleft.x = llx;
 
1331
      thisobj->bbox.lowerleft.y = lly;
 
1332
      thisobj->bbox.width = urx - llx;
 
1333
      thisobj->bbox.height = ury - lly;
 
1334
   }
1310
1335
 
1311
1336
   /* calculate instance-specific values */
1312
1337
   calcbboxinst(thisinst);
1327
1352
   corner.x = origin.x + tinst->bbox.width;
1328
1353
   corner.y = origin.y + tinst->bbox.height;
1329
1354
 
1330
 
#ifdef SCHEMA
1331
1355
   extendschembbox(tinst, &origin, &corner);
1332
 
#endif
1333
1356
 
1334
1357
   width = corner.x - origin.x;
1335
1358
   height = corner.y - origin.y;
1353
1376
void refresh(xcWidget bw, caddr_t clientdata, caddr_t calldata)
1354
1377
{
1355
1378
   drawarea(NULL, NULL, NULL);
1356
 
   drawhbar(areastruct.scrollbarh, NULL, NULL);
1357
 
   drawvbar(areastruct.scrollbarv, NULL, NULL);
 
1379
   if (areastruct.scrollbarh)
 
1380
      drawhbar(areastruct.scrollbarh, NULL, NULL);
 
1381
   if (areastruct.scrollbarv)
 
1382
      drawvbar(areastruct.scrollbarv, NULL, NULL);
1358
1383
   printname(topobject);
1359
1384
}
1360
1385
 
1364
1389
 
1365
1390
void zoomview(xcWidget w, caddr_t clientdata, caddr_t calldata)
1366
1391
{
1367
 
   if (eventmode == NORMAL_MODE || eventmode == COPY2_MODE ||
1368
 
         eventmode == PUSH_MODE || eventmode == PRESS_MODE ||
1369
 
         eventmode == CATALOG_MODE || eventmode == FONTCAT_MODE ||
1370
 
         eventmode == FONTCAT2_MODE) {
 
1392
   if (eventmode == NORMAL_MODE || eventmode == COPY_MODE ||
 
1393
         eventmode == MOVE_MODE || eventmode == CATALOG_MODE ||
 
1394
        eventmode == FONTCAT_MODE || eventmode == EFONTCAT_MODE) {
1371
1395
 
 
1396
#ifdef USE_WIN32_COM
 
1397
      float scale = *(areastruct.vscale);
 
1398
#endif
1372
1399
      centerview(areastruct.topinstance);
 
1400
      invalidate_graphics(topobject);
1373
1401
      areastruct.lastbackground = NULL;
1374
1402
      renderbackground();
1375
1403
      refresh(NULL, NULL, NULL);
 
1404
#ifdef USE_WIN32_COM
 
1405
      if (*(areastruct.vscale) != scale)
 
1406
         win32_fire_event(ZoomChanged);
 
1407
#endif
1376
1408
   }
1377
1409
}
1378
1410
 
1387
1419
   UTransformbyCTM(DCTM, pt1, &newpt1, 1);
1388
1420
   UTransformbyCTM(DCTM, pt2, &newpt2, 1);
1389
1421
 
1390
 
   XDrawLine(dpy, areastruct.areawin, areastruct.gc,
 
1422
   DrawLine(dpy, areastruct.areawin, areastruct.gc,
1391
1423
                newpt1.x, newpt1.y, newpt2.x, newpt2.y); 
1392
1424
1393
1425
 
1395
1427
 
1396
1428
void UDrawLine(XPoint *pt1, XPoint *pt2)
1397
1429
{
1398
 
   short tmpwidth = UTopTransScale(xobjs.pagelist[areastruct.page]->wirewidth);
 
1430
   float tmpwidth = UTopTransScale(xobjs.pagelist[areastruct.page]->wirewidth);
1399
1431
 
1400
 
   XSetLineAttributes(dpy, areastruct.gc, tmpwidth >= 2.0 ? (int)tmpwidth : 
1401
 
        0, LineSolid, CapRound, JoinBevel);
 
1432
   SetLineAttributes(dpy, areastruct.gc, tmpwidth, LineSolid, CapRound, JoinBevel);
1402
1433
   UDrawSimpleLine(pt1, pt2); 
1403
1434
1404
1435
 
1421
1452
   XPoint wpt;
1422
1453
 
1423
1454
   user_to_window(*upt, &wpt);
1424
 
   XSetLineAttributes(dpy, areastruct.gc, 0, LineSolid, CapButt, JoinMiter);
 
1455
   SetThinLineAttributes(dpy, areastruct.gc, 0, LineSolid, CapButt, JoinMiter);
1425
1456
 
1426
1457
   switch(which) {
1427
1458
      case P_POSITION_X:
1449
1480
 
1450
1481
void UDrawXAt(XPoint *wpt)
1451
1482
{
1452
 
   XSetLineAttributes(dpy, areastruct.gc, 0, LineSolid, CapButt, JoinMiter);
1453
 
   XDrawLine(dpy, areastruct.areawin, areastruct.gc, wpt->x - 3,
 
1483
   SetThinLineAttributes(dpy, areastruct.gc, 0, LineSolid, CapButt, JoinMiter);
 
1484
   DrawLine(dpy, areastruct.areawin, areastruct.gc, wpt->x - 3,
1454
1485
                wpt->y - 3, wpt->x + 3, wpt->y + 3);
1455
 
   XDrawLine(dpy, areastruct.areawin, areastruct.gc, wpt->x + 3,
 
1486
   DrawLine(dpy, areastruct.areawin, areastruct.gc, wpt->x + 3,
1456
1487
                wpt->y - 3, wpt->x - 3, wpt->y + 3);
1457
1488
}
1458
1489
 
1468
1499
   UDrawXAt(&wpt);
1469
1500
}
1470
1501
 
1471
 
#ifdef SCHEMA
1472
 
 
1473
1502
/*----------------------------------------------------------------------*/
1474
1503
/* Draw "X" on top level (only for LOCAL and GLOBAL pin labels)         */
1475
1504
/*----------------------------------------------------------------------*/
1483
1512
}
1484
1513
 
1485
1514
/*----------------------------------------------------------------------*/
1486
 
/* Find the "real" width and height of an object including pin labels   */
1487
 
/* and so forth that only show up on a schematic when it is the top-    */
1488
 
/* level object.                                                        */
 
1515
/* Find the "real" width, height, and origin of an object including pin */
 
1516
/* labels and so forth that only show up on a schematic when it is the  */
 
1517
/* top-level object.                                                    */
1489
1518
/*----------------------------------------------------------------------*/
1490
1519
 
1491
 
int toplevelwidth(objinstptr bbinst)
 
1520
int toplevelwidth(objinstptr bbinst, short *rllx)
1492
1521
{
1493
1522
   short llx, urx;
1494
1523
   short origin, corner;
1495
1524
 
1496
 
   if (bbinst->schembbox == NULL) return bbinst->bbox.width;
 
1525
   if (bbinst->schembbox == NULL) {
 
1526
      if (rllx) *rllx = bbinst->bbox.lowerleft.x;
 
1527
      return bbinst->bbox.width;
 
1528
   }
1497
1529
 
1498
1530
   origin = bbinst->bbox.lowerleft.x;
1499
1531
   corner = origin + bbinst->bbox.width;
1504
1536
   bboxcalc(llx, &origin, &corner);
1505
1537
   bboxcalc(urx, &origin, &corner);
1506
1538
 
 
1539
   if (rllx) *rllx = origin;
1507
1540
   return(corner - origin);
1508
1541
}
1509
1542
 
1510
1543
/*----------------------------------------------------------------------*/
1511
1544
 
1512
 
int toplevelheight(objinstptr bbinst)
 
1545
int toplevelheight(objinstptr bbinst, short *rlly)
1513
1546
{
1514
1547
   short lly, ury;
1515
1548
   short origin, corner;
1516
1549
 
1517
 
   if (bbinst->schembbox == NULL) return bbinst->bbox.height;
 
1550
   if (bbinst->schembbox == NULL) {
 
1551
      if (rlly) *rlly = bbinst->bbox.lowerleft.y;
 
1552
      return bbinst->bbox.height;
 
1553
   }
1518
1554
 
1519
1555
   origin = bbinst->bbox.lowerleft.y;
1520
1556
   corner = origin + bbinst->bbox.height;
1525
1561
   bboxcalc(lly, &origin, &corner);
1526
1562
   bboxcalc(ury, &origin, &corner);
1527
1563
 
 
1564
   if (rlly) *rlly = origin;
1528
1565
   return(corner - origin);
1529
1566
}
1530
1567
 
1566
1603
   if (ypoint != NULL) *ypoint += (dir > 0) ? dely : -dely;
1567
1604
}
1568
1605
 
1569
 
#endif
1570
 
 
1571
1606
/*----------------------------------------------------------------------*/
1572
1607
/* Draw line for editing text (position of cursor in string is given by */
1573
1608
/*   tpos (2nd parameter)                                               */
1585
1620
   UPreMultCTM(DCTM, curlabel->position, curlabel->scale, curlabel->rotation);
1586
1621
   tmpjust = flipadjust(curlabel->justify);
1587
1622
 
1588
 
   XSetFunction(dpy, areastruct.gc, GXxor);
1589
 
   XSetForeground(dpy, areastruct.gc, AUXCOLOR ^ BACKGROUND);
 
1623
   SetFunction(dpy, areastruct.gc, GXxor);
 
1624
   SetForeground(dpy, areastruct.gc, AUXCOLOR ^ BACKGROUND);
1590
1625
 
1591
1626
   tmpext = ULength(curlabel->string, areastruct.topinstance, 0.0, tpos, NULL);
1592
1627
   xdist = tmpext.width;
1602
1637
   points[1].x = points[0].x;
1603
1638
   points[1].y = points[0].y + TEXTHEIGHT + 6;
1604
1639
 
1605
 
#ifdef SCHEMA
1606
1640
   if (curlabel->pin) {
1607
1641
      pinadjust(tmpjust, &(points[0].x), &(points[0].y), 1);
1608
1642
      pinadjust(tmpjust, &(points[1].x), &(points[1].y), 1);
1609
1643
   }
1610
 
#endif
1611
1644
 
1612
1645
   /* draw the line */
1613
1646
 
1637
1670
{
1638
1671
   XPoint upt, vpt;
1639
1672
 
1640
 
   XSetForeground(dpy, areastruct.gc, AUXCOLOR ^ BACKGROUND);
1641
 
   XSetFunction(dpy, areastruct.gc, GXxor);
 
1673
   SetForeground(dpy, areastruct.gc, AUXCOLOR ^ BACKGROUND);
 
1674
   SetFunction(dpy, areastruct.gc, GXxor);
1642
1675
 
1643
1676
   user_to_window(cpt, &upt);
1644
1677
   user_to_window(opt, &vpt);
1645
1678
 
1646
 
   XSetLineAttributes(dpy, areastruct.gc, 0, LineOnOffDash, CapButt, JoinMiter);
1647
 
   XDrawLine(dpy, areastruct.areawin, areastruct.gc, vpt.x, vpt.y, upt.x, upt.y);
 
1679
   SetThinLineAttributes(dpy, areastruct.gc, 0, LineOnOffDash, CapButt, JoinMiter);
 
1680
   DrawLine(dpy, areastruct.areawin, areastruct.gc, vpt.x, vpt.y, upt.x, upt.y);
1648
1681
 
1649
 
   XSetLineAttributes(dpy, areastruct.gc, 0, LineSolid, CapButt, JoinMiter);
1650
 
   XDrawLine(dpy, areastruct.areawin, areastruct.gc, upt.x - 3, upt.y - 3,
 
1682
   SetThinLineAttributes(dpy, areastruct.gc, 0, LineSolid, CapButt, JoinMiter);
 
1683
   DrawLine(dpy, areastruct.areawin, areastruct.gc, upt.x - 3, upt.y - 3,
1651
1684
                upt.x + 3, upt.y + 3);
1652
 
   XDrawLine(dpy, areastruct.areawin, areastruct.gc, upt.x + 3, upt.y - 3,
 
1685
   DrawLine(dpy, areastruct.areawin, areastruct.gc, upt.x + 3, upt.y - 3,
1653
1686
                upt.x - 3, upt.y + 3);
1654
1687
 
1655
 
   XSetFunction(dpy, areastruct.gc, areastruct.gctype);
1656
 
   XSetForeground(dpy, areastruct.gc, areastruct.gccolor);
 
1688
   SetFunction(dpy, areastruct.gc, areastruct.gctype);
 
1689
   SetForeground(dpy, areastruct.gc, areastruct.gccolor);
1657
1690
}
1658
1691
 
1659
1692
/*-------------------------------------------------------------------------*/
1665
1698
   user_to_window(origin, &worig);
1666
1699
   user_to_window(corner, &wcorn);
1667
1700
 
1668
 
   XSetFunction(dpy, areastruct.gc, GXxor);
1669
 
   XSetForeground(dpy, areastruct.gc, AUXCOLOR ^ BACKGROUND);
1670
 
   XSetLineAttributes(dpy, areastruct.gc, 0, LineSolid, CapRound, JoinBevel);
 
1701
   SetFunction(dpy, areastruct.gc, GXxor);
 
1702
   SetForeground(dpy, areastruct.gc, AUXCOLOR ^ BACKGROUND);
 
1703
   SetThinLineAttributes(dpy, areastruct.gc, 0, LineSolid, CapRound, JoinBevel);
1671
1704
 
1672
 
   XDrawLine(dpy, areastruct.areawin, areastruct.gc, worig.x, worig.y,
 
1705
   DrawLine(dpy, areastruct.areawin, areastruct.gc, worig.x, worig.y,
1673
1706
                worig.x, wcorn.y);
1674
 
   XDrawLine(dpy, areastruct.areawin, areastruct.gc, worig.x, wcorn.y,
 
1707
   DrawLine(dpy, areastruct.areawin, areastruct.gc, worig.x, wcorn.y,
1675
1708
                wcorn.x, wcorn.y);
1676
 
   XDrawLine(dpy, areastruct.areawin, areastruct.gc, wcorn.x, wcorn.y,
 
1709
   DrawLine(dpy, areastruct.areawin, areastruct.gc, wcorn.x, wcorn.y,
1677
1710
                wcorn.x, worig.y);
1678
 
   XDrawLine(dpy, areastruct.areawin, areastruct.gc, wcorn.x, worig.y,
 
1711
   DrawLine(dpy, areastruct.areawin, areastruct.gc, wcorn.x, worig.y,
1679
1712
                worig.x, worig.y);
1680
1713
}
1681
1714
 
 
1715
/*----------------------------------------------------------------------*/
 
1716
/* Draw a box indicating the dimensions of the edit element that most   */
 
1717
/* closely reach the position "corner".                                 */
 
1718
/*----------------------------------------------------------------------*/
 
1719
 
 
1720
void UDrawRescaleBox(XPoint *corner)
 
1721
{
 
1722
   XPoint       origpoints[5], newpoints[5];
 
1723
   genericptr   rgen;
 
1724
   float        savescale, newscale, lastscale, tempscale;
 
1725
   long         mindist, testdist, lastmindist;
 
1726
   labelptr     rlab;
 
1727
   int          i, j, idx;
 
1728
 
 
1729
   /* To be done---draw a box around each selected part, not    */
 
1730
   /* just the first one.                                       */
 
1731
 
 
1732
   SetFunction(dpy, areastruct.gc, GXxor);
 
1733
   SetForeground(dpy, areastruct.gc, AUXCOLOR ^ BACKGROUND);
 
1734
   SetThinLineAttributes(dpy, areastruct.gc, 0, LineSolid, CapRound, JoinBevel);
 
1735
   
 
1736
   for (j = 0; j < areastruct.selects; j++) {
 
1737
      rgen = SELTOGENERIC(areastruct.selectlist + j);
 
1738
 
 
1739
      switch(ELEMENTTYPE(rgen)) {
 
1740
         case LABEL:
 
1741
            rlab = (labelptr)rgen;
 
1742
            savescale = rlab->scale;
 
1743
            newscale = lastscale = rlab->scale * 2;
 
1744
            mindist = LONG_MAX;
 
1745
            while (mindist > 4) {
 
1746
               rlab->scale = newscale;
 
1747
               labelbbox(rlab, newpoints, areastruct.topinstance);
 
1748
               newpoints[5] = newpoints[0];
 
1749
               lastmindist = mindist;
 
1750
               mindist = LONG_MAX;
 
1751
               for (i = 0; i < 4; i++) {
 
1752
                  testdist = finddist(&newpoints[i], &newpoints[i+1], corner);
 
1753
                  if (testdist < mindist)
 
1754
                     mindist = testdist;
 
1755
               }
 
1756
               if (mindist == lastmindist)
 
1757
                  break;
 
1758
               else if (lastmindist == LONG_MAX)
 
1759
                  newscale /= 2;
 
1760
               else {
 
1761
                  tempscale = (fabs)((newscale * lastmindist) - (lastscale * mindist)) / 
 
1762
                                (abs)(lastmindist - mindist);
 
1763
                  lastscale = newscale;
 
1764
                  newscale = tempscale;
 
1765
               }
 
1766
            }
 
1767
            rlab->scale = savescale;
 
1768
            break;
 
1769
         case GRAPHIC:
 
1770
            break;
 
1771
         case OBJINST:
 
1772
            break;
 
1773
         /* Note:  should be able to handle other elements, as well */
 
1774
      }
 
1775
 
 
1776
      UTransformbyCTM(DCTM, newpoints, origpoints, 4);
 
1777
      strokepath(origpoints, 4, 0, 1);
 
1778
   }
 
1779
}
 
1780
 
1682
1781
/*-------------------------------------------------------------------------*/
1683
1782
void UDrawBBox()
1684
1783
{
1692
1791
   corner.x = origin.x + bbinst->bbox.width;
1693
1792
   corner.y = origin.y + bbinst->bbox.height;
1694
1793
 
1695
 
#ifdef SCHEMA
1696
1794
   /* Include any schematic labels in the bounding box. */
1697
1795
   extendschembbox(bbinst, &origin, &corner);
1698
 
#endif
1699
1796
 
1700
1797
   user_to_window(origin, &worig);
1701
1798
   user_to_window(corner, &wcorn);
1702
1799
 
1703
 
   XSetForeground(dpy, areastruct.gc, BBOXCOLOR);
1704
 
   XDrawLine(dpy, areastruct.areawin, areastruct.gc, worig.x, worig.y,
 
1800
   SetForeground(dpy, areastruct.gc, BBOXCOLOR);
 
1801
   DrawLine(dpy, areastruct.areawin, areastruct.gc, worig.x, worig.y,
1705
1802
                worig.x, wcorn.y);
1706
 
   XDrawLine(dpy, areastruct.areawin, areastruct.gc, worig.x, wcorn.y,
 
1803
   DrawLine(dpy, areastruct.areawin, areastruct.gc, worig.x, wcorn.y,
1707
1804
                wcorn.x, wcorn.y);
1708
 
   XDrawLine(dpy, areastruct.areawin, areastruct.gc, wcorn.x, wcorn.y,
 
1805
   DrawLine(dpy, areastruct.areawin, areastruct.gc, wcorn.x, wcorn.y,
1709
1806
                wcorn.x, worig.y);
1710
 
   XDrawLine(dpy, areastruct.areawin, areastruct.gc, wcorn.x, worig.y,
 
1807
   DrawLine(dpy, areastruct.areawin, areastruct.gc, wcorn.x, worig.y,
1711
1808
                worig.x, worig.y);
1712
1809
}
1713
1810
 
1719
1816
{
1720
1817
   char         solidpart;
1721
1818
   char         dashstring[3];
1722
 
   short        tmpwidth;
 
1819
   float        tmpwidth;
 
1820
   short        minwidth;
1723
1821
 
1724
 
   tmpwidth = max(1, UTopTransScale(xobjs.pagelist[areastruct.page]->wirewidth *
1725
 
        width));
 
1822
   tmpwidth = UTopTransScale(xobjs.pagelist[areastruct.page]->wirewidth * width);
 
1823
   minwidth = max(1, (short)tmpwidth);
1726
1824
 
1727
1825
   if (style & FILLED || (!(style & FILLED) && style & OPAQUE)) {
1728
1826
      if ((style & FILLSOLID) == FILLSOLID)
1729
 
         XSetFillStyle(dpy, areastruct.gc, FillSolid);
 
1827
         SetFillStyle(dpy, areastruct.gc, FillSolid);
1730
1828
      else if (!(style & FILLED)) {
1731
 
         XSetFillStyle(dpy, areastruct.gc, FillOpaqueStippled); 
1732
 
         XSetStipple(dpy, areastruct.gc, STIPPLE[7]);
 
1829
         SetFillStyle(dpy, areastruct.gc, FillOpaqueStippled); 
 
1830
         SetStipple(dpy, areastruct.gc, 7);
1733
1831
      }
1734
1832
      else {
1735
1833
         if (style & OPAQUE)
1736
 
            XSetFillStyle(dpy, areastruct.gc, FillOpaqueStippled);
 
1834
            SetFillStyle(dpy, areastruct.gc, FillOpaqueStippled);
1737
1835
         else
1738
 
            XSetFillStyle(dpy, areastruct.gc, FillStippled);
1739
 
         XSetStipple(dpy, areastruct.gc, STIPPLE[ (style &
1740
 
                FILLSOLID) >> 5] );
 
1836
            SetFillStyle(dpy, areastruct.gc, FillStippled);
 
1837
         SetStipple(dpy, areastruct.gc, ((style & FILLSOLID) >> 5));
1741
1838
      }
1742
 
      XFillPolygon(dpy, areastruct.areawin, areastruct.gc, pathlist, number, Nonconvex,
 
1839
      FillPolygon(dpy, areastruct.areawin, areastruct.gc, pathlist, number, Nonconvex,
1743
1840
                CoordModeOrigin);
1744
1841
      /* return to original state */
1745
 
      XSetFillStyle(dpy, areastruct.gc, FillSolid);
 
1842
      SetFillStyle(dpy, areastruct.gc, FillSolid);
1746
1843
   }
1747
1844
   if (!(style & NOBORDER)) {
1748
1845
      /* set up dots or dashes */
1749
 
      if (style & DASHED) solidpart = (char)(4 * tmpwidth);
1750
 
      else if (style & DOTTED) solidpart = (char)tmpwidth;
1751
 
      sprintf(dashstring, "%c%c", solidpart, (char)(4 * tmpwidth));
 
1846
      if (style & DASHED) solidpart = (char)(4 * minwidth);
 
1847
      else if (style & DOTTED) solidpart = (char)minwidth;
 
1848
      sprintf(dashstring, "%c%c", solidpart, (char)(4 * minwidth));
1752
1849
      if (style & (DASHED | DOTTED)) {
1753
 
         XSetDashes(dpy, areastruct.gc, 0, dashstring, 2);
1754
 
         XSetLineAttributes(dpy, areastruct.gc, tmpwidth >= 2.0 ?
1755
 
            (int)tmpwidth : 0, LineOnOffDash, CapButt, JoinBevel);
 
1850
         SetDashes(dpy, areastruct.gc, 0, dashstring, 2);
 
1851
         SetLineAttributes(dpy, areastruct.gc, tmpwidth, LineOnOffDash,
 
1852
                CapButt, JoinMiter);
1756
1853
      }
1757
1854
      else
1758
 
         XSetLineAttributes(dpy, areastruct.gc, tmpwidth >= 2.0 ?
1759
 
            (int)tmpwidth : 0, LineSolid, CapRound, JoinBevel);
 
1855
         SetLineAttributes(dpy, areastruct.gc, tmpwidth, LineSolid,
 
1856
                (style & SQUARECAP) ? CapProjecting : CapRound, JoinMiter);
1760
1857
 
1761
1858
      /* draw the spline and close off if so specified */
1762
 
      XDrawLines(dpy, areastruct.areawin, areastruct.gc, pathlist,
 
1859
      DrawLines(dpy, areastruct.areawin, areastruct.gc, pathlist,
1763
1860
                number, CoordModeOrigin);
1764
1861
      if (!(style & UNCLOSED))
1765
 
         XDrawLine(dpy, areastruct.areawin, areastruct.gc, pathlist[0].x,
 
1862
         DrawLine(dpy, areastruct.areawin, areastruct.gc, pathlist[0].x,
1766
1863
                pathlist[0].y, pathlist[number - 1].x, pathlist[number - 1].y);
1767
1864
   }
1768
1865
}
1831
1928
   
1832
1929
   for (genpath = thepath->plist; genpath < thepath->plist + thepath->parts;
1833
1930
          genpath++) {
1834
 
      switch((*genpath)->type) {
 
1931
      switch(ELEMENTTYPE(*genpath)) {
1835
1932
         case POLYGON:
1836
1933
            thepoly = TOPOLY(genpath);
1837
1934
            pathsegs += thepoly->number;
1870
1967
void UDrawObject(objinstptr theinstance, short level, int passcolor, pushlistptr *stack)
1871
1968
{
1872
1969
   genericptr   *areagen;
1873
 
   short        tmpwidth;
 
1970
   float        tmpwidth;
1874
1971
   int          defaultcolor = passcolor;
1875
1972
   int          curcolor = passcolor;
1876
 
   XPoint       bboxin, bboxout[2];
 
1973
   int          thispart;
 
1974
   XPoint       bboxin[2], bboxout[2];
1877
1975
   u_char       xm, ym;
1878
1976
   objectptr    theobject = theinstance->thisobject;
1879
1977
 
1890
1988
 
1891
1989
   /* do a quick test for intersection with the display window */
1892
1990
 
1893
 
   UTransformbyCTM(DCTM, &(theobject->bbox.lowerleft), &(bboxout[0]), 1);
1894
 
   bboxin.x = theobject->bbox.lowerleft.x + theobject->bbox.width;
1895
 
   bboxin.y = theobject->bbox.lowerleft.y + theobject->bbox.height; 
1896
 
   UTransformbyCTM(DCTM, &bboxin, &(bboxout[1]), 1);
 
1991
   bboxin[0].x = theobject->bbox.lowerleft.x;
 
1992
   bboxin[0].y = theobject->bbox.lowerleft.y;
 
1993
   bboxin[1].x = theobject->bbox.lowerleft.x + theobject->bbox.width;
 
1994
   bboxin[1].y = theobject->bbox.lowerleft.y + theobject->bbox.height; 
 
1995
   if (level == 0)
 
1996
      extendschembbox(theinstance, &(bboxin[0]), &(bboxin[1]));
 
1997
   UTransformbyCTM(DCTM, bboxin, bboxout, 2);
1897
1998
 
1898
1999
   xm = (bboxout[0].x < bboxout[1].x) ? 0 : 1;  
1899
2000
   ym = (bboxout[0].y < bboxout[1].y) ? 0 : 1;  
1907
2008
     /* draw all of the elements */
1908
2009
   
1909
2010
     tmpwidth = UTopTransScale(xobjs.pagelist[areastruct.page]->wirewidth);
1910
 
     XSetLineAttributes(dpy, areastruct.gc, tmpwidth >= 2.0 ? (int)tmpwidth :
1911
 
                0, LineSolid, CapRound, JoinBevel);
1912
 
 
1913
 
     for (areagen = theobject->plist; areagen < theobject->plist +
1914
 
           theobject->parts; areagen++) {
 
2011
     SetLineAttributes(dpy, areastruct.gc, tmpwidth, LineSolid, CapRound,
 
2012
                JoinBevel);
 
2013
 
 
2014
     /* guard against plist being regenerated during a redraw by the    */
 
2015
     /* expression parameter mechanism (should that be prohibited?)     */
 
2016
 
 
2017
     for (thispart = 0; thispart < theobject->parts; thispart++) {
 
2018
       areagen = theobject->plist + thispart;
 
2019
       if ((*areagen)->type & DRAW_HIDE) continue;
1915
2020
 
1916
2021
       if (defaultcolor != DOFORALL) {
1917
2022
          if ((*areagen)->color != curcolor) {
1923
2028
          }
1924
2029
       }
1925
2030
 
1926
 
       switch((*areagen)->type) {
 
2031
       switch(ELEMENTTYPE(*areagen)) {
1927
2032
          case(POLYGON):
1928
2033
             if (level == 0 || !((TOPOLY(areagen))->style & BBOX))
1929
2034
                UDrawPolygon(TOPOLY(areagen));
1940
2045
          case(PATH):
1941
2046
             UDrawPath(TOPATH(areagen));
1942
2047
             break;
 
2048
 
 
2049
          case(GRAPHIC):
 
2050
             UDrawGraphic(TOGRAPHIC(areagen));
 
2051
             break;
1943
2052
   
1944
 
          case(OBJECT):
 
2053
          case(OBJINST):
1945
2054
             if (areastruct.editinplace && stack && (TOOBJINST(areagen)
1946
2055
                        == areastruct.topinstance)) {
1947
2056
                /* If stack matches areastruct.stack, then don't draw */
1958
2067
             break;
1959
2068
   
1960
2069
          case(LABEL): 
1961
 
#ifdef SCHEMA
1962
2070
             if (level == 0 || TOLABEL(areagen)->pin == False ||
1963
2071
                        (TOLABEL(areagen)->justify & PINVISIBLE))
1964
 
#endif
1965
2072
             UDrawString(TOLABEL(areagen), curcolor, theinstance);
1966
 
#ifdef SCHEMA
1967
2073
             else if (level == 1 && TOLABEL(areagen)->pin &&
1968
2074
                        TOLABEL(areagen)->pin != INFO && areastruct.pinpointon)
1969
2075
                UDrawXDown(TOLABEL(areagen));
1970
 
#endif
1971
2076
             break;
 
2077
 
1972
2078
       }
1973
2079
     }
1974
2080
 
1982
2088
   if (stack) pop_stack(stack);
1983
2089
}
1984
2090
 
1985
 
/*-------------------------------------------------------------------------*/
 
2091
/*----------------------------------------------------------------------*/
 
2092
/* Recursively run through the current page and find any labels which   */
 
2093
/* are declared to be style LATEX.  If "checkonly" is present, we set   */
 
2094
/* it to TRUE or FALSE depending on whether or not LATEX labels have    */
 
2095
/* been encountered.  If NULL, then we write LATEX output appropriately */
 
2096
/* to a file named with the page filename + suffix ".tex".              */
 
2097
/*----------------------------------------------------------------------*/
 
2098
 
 
2099
void UDoLatex(objinstptr theinstance, short level, FILE *f,
 
2100
        float scale, int tx, int ty, Boolean *checkonly)
 
2101
{
 
2102
   XPoint       lpos, xlpos;
 
2103
   XfPoint      xfpos;
 
2104
   labelptr     thislabel;
 
2105
   genericptr   *areagen;
 
2106
   objectptr    theobject = theinstance->thisobject;
 
2107
   char         *ltext;
 
2108
   int          lrjust, tbjust;
 
2109
 
 
2110
   UPushCTM();
 
2111
   if (level != 0)
 
2112
       UPreMultCTM(DCTM, theinstance->position, theinstance->scale,
 
2113
                        theinstance->rotation);
 
2114
 
 
2115
   /* make parameter substitutions */
 
2116
   psubstitute(theinstance);
 
2117
 
 
2118
   /* find all of the elements */
 
2119
   
 
2120
   for (areagen = theobject->plist; areagen < theobject->plist +
 
2121
           theobject->parts; areagen++) {
 
2122
 
 
2123
      switch(ELEMENTTYPE(*areagen)) {
 
2124
         case(OBJINST):
 
2125
            UDoLatex(TOOBJINST(areagen), level + 1, f, scale, tx, ty, checkonly);
 
2126
            break;
 
2127
   
 
2128
         case(LABEL): 
 
2129
            thislabel = TOLABEL(areagen);
 
2130
            if (level == 0 || thislabel->pin == False ||
 
2131
                        (thislabel->justify & PINVISIBLE))
 
2132
                if (thislabel->justify & LATEXLABEL) {
 
2133
                    if (checkonly) {
 
2134
                       *checkonly = TRUE;
 
2135
                       return;
 
2136
                    }
 
2137
                    else {
 
2138
                       lpos.x = thislabel->position.x;
 
2139
                       lpos.y = thislabel->position.y;
 
2140
                       UTransformbyCTM(DCTM, &lpos, &xlpos, 1);
 
2141
                       xlpos.x += tx;
 
2142
                       xlpos.y += ty;
 
2143
                       xfpos.x = (float)xlpos.x * scale;
 
2144
                       xfpos.y = (float)xlpos.y * scale;
 
2145
                       xfpos.x /= 72.0;
 
2146
                       xfpos.y /= 72.0;
 
2147
                       xfpos.x -= 1.0;
 
2148
                       xfpos.y -= 1.0;
 
2149
                       xfpos.x += 0.056;
 
2150
                       xfpos.y += 0.056;
 
2151
                       ltext = textprint(thislabel->string, theinstance);
 
2152
                       tbjust = thislabel->justify & (NOTBOTTOM | TOP);
 
2153
                       lrjust = thislabel->justify & (NOTLEFT | RIGHT);
 
2154
                       fprintf(f, "\\putbox{%3.2fin}{%3.2fin}{",
 
2155
                                xfpos.x, xfpos.y);
 
2156
                       if (lrjust == (NOTLEFT | RIGHT)) fprintf(f, "\\rightbox{");
 
2157
                       else if (lrjust == NOTLEFT) fprintf(f, "\\centbox{");
 
2158
                       if (tbjust == (NOTBOTTOM | TOP)) fprintf(f, "\\topbox{");
 
2159
                       else if (tbjust == NOTBOTTOM) fprintf(f, "\\midbox{");
 
2160
                       fprintf(f, "%s", ltext);
 
2161
                       if (lrjust != NORMAL) fprintf(f, "}");
 
2162
                       if (tbjust != NORMAL) fprintf(f, "}");
 
2163
                       fprintf(f, "}%%\n");
 
2164
                       free(ltext);
 
2165
                    }
 
2166
                }
 
2167
            break;
 
2168
       }
 
2169
   }
 
2170
   UPopCTM();
 
2171
}
 
2172
 
 
2173
/*----------------------------------------------------------------------*/
 
2174
/*  Top level routine for writing LATEX output.                         */
 
2175
/*----------------------------------------------------------------------*/
 
2176
 
 
2177
void TopDoLatex()
 
2178
{
 
2179
   FILE *f;
 
2180
   float psscale;
 
2181
   int tx, ty, width, height;
 
2182
   XPoint origin;
 
2183
   Boolean checklatex = FALSE;
 
2184
   char filename[50];
 
2185
 
 
2186
   UDoLatex(areastruct.topinstance, 0, NULL, 1.0, 0, 0, &checklatex);
 
2187
 
 
2188
   if (checklatex == FALSE) return;     /* No LaTeX labels to write */
 
2189
 
 
2190
   sprintf(filename, "%s.tex", xobjs.pagelist[areastruct.page]->filename);
 
2191
   f = fopen(filename, "w");
 
2192
 
 
2193
   fprintf(f, "%% XCircuit output \"%s\" for LaTeX input from %s.ps\n",
 
2194
                filename, xobjs.pagelist[areastruct.page]->filename);
 
2195
   fprintf(f, "\\def\\putbox#1#2#3{\\makebox[0in][l]{\\makebox[#1][l]{}"
 
2196
                "\\raisebox{\\baselineskip}[0in][0in]"
 
2197
                "{\\raisebox{#2}[0in][0in]{#3}}}}\n");
 
2198
   fprintf(f, "\\def\\rightbox#1{\\makebox[0in][r]{#1}}\n");
 
2199
   fprintf(f, "\\def\\centbox#1{\\makebox[0in]{#1}}\n");
 
2200
   fprintf(f, "\\def\\topbox#1{\\raisebox{-\\baselineskip}[0in][0in]{#1}}\n");
 
2201
   fprintf(f, "\\def\\midbox#1{\\raisebox{-0.5\\baselineskip}[0in][0in]{#1}}\n");
 
2202
   fprintf(f, "\\begin{flushleft}\n");
 
2203
 
 
2204
   filename[strlen(filename) - 4] = '\0';
 
2205
   if (strchr(filename, '.') == NULL)
 
2206
      sprintf(filename + strlen(filename), ".ps");
 
2207
 
 
2208
   fprintf(f, "\\epsfig{file=%s}\\\\\n", filename);
 
2209
 
 
2210
   psscale = getpsscale(xobjs.pagelist[areastruct.page]->outscale,
 
2211
                areastruct.page);
 
2212
 
 
2213
   width = toplevelwidth(areastruct.topinstance, &origin.x);
 
2214
   height = toplevelheight(areastruct.topinstance, &origin.y);
 
2215
 
 
2216
   tx = (int)(72 / psscale) - origin.x,
 
2217
   ty = (int)(72 / psscale) - origin.y;
 
2218
 
 
2219
   fprintf(f, "%% translate x=%d y=%d scale %3.2f\n", tx, ty, psscale);
 
2220
 
 
2221
   UPushCTM();          /* Save current state */
 
2222
   UResetCTM(DCTM);     /* Set to identity matrix */
 
2223
   UDoLatex(areastruct.topinstance, 0, f, psscale, tx, ty, NULL);
 
2224
   UPopCTM();           /* Restore state */
 
2225
 
 
2226
   fprintf(f, "\\end{flushleft}\n");
 
2227
   fclose(f);
 
2228
}
 
2229