47
51
extern short fontcount;
48
52
extern fontinfo *fonts;
54
/*------------------------------------------------------*/
55
/* Check if a library exists */
56
/*-------------------------------------------------------*/
50
58
/*---------------------------------------------------------*/
51
59
/* Find the Helvetica font for use in labeling the objects */
52
60
/*---------------------------------------------------------*/
88
96
/* Pop the object being edited from the push stack. */
90
popobject(NULL, NULL, NULL);
98
popobject(NULL, (pointertype)1, NULL);
93
101
/*------------------------------------------------------*/
98
106
/* page number of page to the right. */
99
107
/*------------------------------------------------------*/
101
int pageposition(short libmode, XButtonEvent *event, int mode)
109
int pageposition(short libmode, int x, int y, int mode)
103
111
int xin, yin, bpage, pages;
104
112
int gxsize, gysize, xdel, ydel;
106
114
pages = (libmode == PAGELIB) ? xobjs.pages : xobjs.numlibs;
107
115
computespacing(libmode, &gxsize, &gysize, &xdel, &ydel);
108
window_to_user(event->x, event->y, &areastruct.save);
116
window_to_user(x, y, &areastruct.save);
110
118
if (mode == 0) { /* On-page */
111
119
if (areastruct.save.x >= 0 && areastruct.save.y <= 0) {
276
284
/*------------------------------------------------------*/
285
/* Check if a library (given by name) exists. If it */
286
/* does, return the library number. If not, return -1 */
287
/*------------------------------------------------------*/
289
int check_library(char *libname)
293
for (i = 0; i < xobjs.numlibs; i++)
294
if (!strcmp(xobjs.libtop[i + LIBRARY]->thisobject->name, libname))
300
/*------------------------------------------------------*/
277
301
/* ButtonPress handler during page catalog viewing mode */
278
302
/*------------------------------------------------------*/
280
void pagecatbutton(XButtonEvent *event)
304
void pagecat_op(int op, int x, int y)
288
312
if (mode == LIBRARY) return; /* Something went wrong if this happens */
290
if (event->button == Button1 || event->button == Button2) {
291
if ((bpage = pageposition(mode, event, 0)) >= 0) {
314
if (op != XCF_Cancel) {
315
if ((bpage = pageposition(mode, x, y, 0)) >= 0) {
294
317
if (eventmode == ASSOC_MODE) {
295
318
if (mode == PAGELIB) {
296
319
/* using changepage() allows use of new page for schematic */
299
322
schemassoc(topobject, areastruct.stack->thisinst->thisobject);
300
323
/* pop back to calling (symbol) page */
302
eventmode = PRESS_MODE;
325
eventmode = NORMAL_MODE;
328
areastruct.lastlibrary = bpage;
305
329
startcatalog(NULL, (pointertype)(LIBRARY + bpage), NULL);
311
if (event->button == Button1) {
333
else if (op == XCF_Select) {
334
if (mode == PAGELIB) /* No such method for LIBLIB is defined. */
335
select_add_element(OBJINST);
337
else if ((op == XCF_Library_Pop) || (op == XCF_Finish)) {
313
339
/* like catreturn(), but don't actually go to the popped page */
315
341
eventmode = NORMAL_MODE;
316
342
if (mode == PAGELIB) {
318
eventmode = PRESS_MODE;
321
346
startcatalog(NULL, (pointertype)(LIBRARY + bpage), NULL);
326
if (mode == PAGELIB) /* No such method for LIBLIB is defined. */
327
objectselect(OBJECT);
382
403
objinstptr newpageinst(objectptr pageobj)
384
405
objinstptr newinst = (objinstptr) malloc(sizeof(objinst));
385
objectdefaults(newinst, pageobj, 0, 0);
386
newinst->type = OBJECT;
406
instancedefaults(newinst, pageobj, 0, 0);
407
newinst->type = OBJINST;
387
408
newinst->color = DEFAULTCOLOR;
493
513
(*pagelabel)->color = DEFAULTCOLOR;
494
514
(*pagelabel)->scale = 0.75;
495
515
(*pagelabel)->string->data.font = fval;
496
(*pagelabel)->num_params = 0;
497
516
(*pagelabel)->passed = NULL;
498
517
strptr = makesegment(&((*pagelabel)->string), NULL);
499
518
strptr->type = TEXT_STRING;
533
552
for (i = 0; i < libinst->parts; i++) {
534
553
gelem = libinst->plist + i;
535
if ((*gelem)->type == OBJECT) {
554
if (IS_OBJINST(*gelem)) {
536
555
pinst = TOOBJINST(gelem);
537
556
if (pinst->thisobject == compobj) {
538
557
/* recalculate scale and position of the object instance */
637
656
short llx, lly, width, height;
658
int totalarea, targetwidth;
639
661
/* Also make composelib() a wrapper for composepagelib() */
640
662
if ((mode > FONTLIB) && (mode < LIBRARY)) {
641
663
composepagelib(mode);
647
669
/* call reset(), we find the pointer to the instance and NULL it. */
649
671
for (pgen = libpage->plist; pgen < libpage->plist + libpage->parts; pgen++)
650
if ((*pgen)->type == OBJECT) *pgen = NULL;
672
if (IS_OBJINST(*pgen)) *pgen = NULL;
652
674
reset(libpage, NORMAL);
654
/* Return if library defines no objects */
676
/* Return if library defines no objects or virtual instances */
656
if (xobjs.userlibs[mode - LIBRARY].number == 0) return;
678
if (xobjs.userlibs[mode - LIBRARY].instlist == NULL) return;
658
680
/* Find the Helvetica font for use in labeling the objects */
660
682
fval = findhelvetica();
684
/* experimental: attempt to produce a library with the same aspect */
685
/* ratio as the drawing window. */
688
for (spec = xobjs.userlibs[mode - LIBRARY].instlist; spec != NULL;
690
libobj = spec->thisinst->thisobject;
692
/* "Hidden" objects are not drawn */
693
if (libobj->hidden == True) continue;
695
drawinst = spec->thisinst;
696
drawinst->position.x = 0;
697
drawinst->position.y = 0;
699
/* Get the bounding box of the instance in the page's coordinate system */
700
calcinstbbox((genericptr *)(&drawinst), &llx, &lly, &width, &height);
701
width -= llx; /* convert urx to width */
702
height -= lly; /* convert ury to height */
703
width += 30; /* space padding */
704
height += 30; /* height padding */
705
if (width < 200) width = 200; /* minimum box width */
706
if (height < 220) height = 220; /* minimum box height */
707
totalarea += (width * height);
710
scale = (double)totalarea / (double)(areastruct.width * areastruct.height);
711
targetwidth = (int)(sqrt(scale) * (double)areastruct.width);
662
713
/* generate the list of object instances and their labels */
664
715
for (spec = xobjs.userlibs[mode - LIBRARY].instlist; spec != NULL;
802
854
+ areastruct.selects; newselect++) {
803
855
libobj = SELTOOBJINST(newselect);
805
if (libobj->thisobject->num_params == 0) {
857
if (libobj->thisobject->params == NULL) {
806
858
Wprintf("Virtual copy allowed only on objects with paramters.");
807
859
/* (because currently there's no way to adjust rotation/scale */
808
860
/* of a non-parameterized instance from inside the library, */
907
959
else { /* All's clear to delete. */
909
/* First remove any instances of this object in the delete buffer */
911
for (compobj = xobjs.delbuffer.library; compobj != xobjs.delbuffer.library +
912
xobjs.delbuffer.number; compobj++) {
913
for (testobj = (*compobj)->plist; testobj < (*compobj)->plist
914
+ (*compobj)->parts; testobj++) {
915
if ((*testobj)->type == OBJECT) {
916
if (TOOBJINST(testobj)->thisobject == libobj->thisobject) {
917
free(TOOBJINST(testobj));
918
for (tobj = testobj; tobj < (*compobj)->plist
919
+ (*compobj)->parts - 1; tobj++) {
920
(*tobj) = (*(tobj + 1));
961
/* Clear the undo stack so that any references to this object */
962
/* won't screw up the database (this could be kinder & gentler */
963
/* by first checking if there are any references to the object */
964
/* in the undo stack. . . */
968
/* Next, remove the object from the library page. */
928
970
for (tlib = libpage; tlib < libpage + *libpobjs; tlib++)
929
971
if ((*tlib) == libobj->thisobject) {
1043
1085
/* Rearrange objects in the library */
1044
1086
/*------------------------------------------------------*/
1046
void catmove(XKeyEvent *event)
1088
void catmove(int x, int y)
1048
1090
int i, j, s1, s2, ocentx, ocenty, rangex, rangey;
1049
1091
liblistptr spec;
1091
1133
else { /* one object selected; find place to put from cursor position */
1093
window_to_user(event->x, event->y, &areastruct.save);
1135
window_to_user(x, y, &areastruct.save);
1096
1138
for (j = 0, spec = xobjs.userlibs[i].instlist; spec != NULL;
1174
1217
(*newobj)->pcorner.x = oldobj->pcorner.x;
1175
1218
(*newobj)->pcorner.y = oldobj->pcorner.y;
1176
1219
(*newobj)->viewscale = oldobj->viewscale;
1178
1220
/* don't attach the same schematic. . . */
1179
1221
(*newobj)->symschem = NULL;
1222
/* don't copy highlights */
1223
(*newobj)->highlight.netlist = NULL;
1224
(*newobj)->highlight.thisinst = NULL;
1181
1226
/* Copy the parameter structure */
1182
(*newobj)->num_params = oldobj->num_params;
1183
(*newobj)->params = (oparamptr *)malloc(oldobj->num_params *
1185
for (i = 0; i < oldobj->num_params; i++) {
1186
(*newobj)->params[i] = (oparamptr) malloc(sizeof(oparam));
1187
(*newobj)->params[i]->type = oldobj->params[i]->type;
1188
switch (oldobj->params[i]->type) {
1227
(*newobj)->params = NULL;
1228
for (ops = oldobj->params; ops != NULL; ops = ops->next) {
1229
newops = (oparamptr)malloc(sizeof(oparam));
1230
newops->next = (*newobj)->params;
1231
newops->key = strdup(ops->key);
1232
(*newobj)->params = newops;
1233
newops->type = ops->type;
1234
newops->which = ops->which;
1235
switch (ops->type) {
1190
(*newobj)->params[i]->parameter.ivalue =
1191
oldobj->params[i]->parameter.ivalue;
1237
newops->parameter.ivalue = ops->parameter.ivalue;
1194
(*newobj)->params[i]->parameter.fvalue =
1195
oldobj->params[i]->parameter.fvalue;
1240
newops->parameter.fvalue = ops->parameter.fvalue;
1197
1242
case XC_STRING:
1198
(*newobj)->params[i]->parameter.string =
1199
stringcopy(oldobj->params[i]->parameter.string);
1243
newops->parameter.string = stringcopy(ops->parameter.string);
1246
newops->parameter.expr = strdup(ops->parameter.expr);
1204
1251
(*newobj)->schemtype = oldobj->schemtype;
1205
(*newobj)->netlist = NULL;
1206
(*newobj)->portlist = NULL;
1207
(*newobj)->calllist = NULL;
1252
(*newobj)->netnames = NULL;
1253
(*newobj)->ports = NULL;
1254
(*newobj)->calls = NULL;
1255
(*newobj)->polygons = NULL;
1256
(*newobj)->labels = NULL;
1208
1257
(*newobj)->valid = False;
1209
1258
(*newobj)->traversed = False;
1210
(*newobj)->devname = NULL;
1212
1259
(*newobj)->hidden = False;
1214
1261
/* copy over all the elements of the original object */
1217
1264
(*newobj)->plist = (genericptr *)malloc(sizeof(genericptr));
1219
1266
for (i = 0; i < oldobj->parts; i++) {
1220
switch((*(oldobj->plist + i))->type) {
1267
switch(ELEMENTTYPE(*(oldobj->plist + i))) {
1222
1269
register pathptr *npath, cpath = TOPATH(oldobj->plist + i);
1223
1270
register genericptr *gpart;
1285
1331
clabel = TOLABEL(oldobj->plist + i);
1286
1332
NEW_LABEL(nlabel, (*newobj));
1287
(*nlabel)->rotation = clabel->rotation;
1288
(*nlabel)->color = clabel->color;
1289
(*nlabel)->position.x = clabel->position.x;
1290
(*nlabel)->position.y = clabel->position.y;
1291
(*nlabel)->scale = clabel->scale;
1292
(*nlabel)->justify = clabel->justify;
1293
(*nlabel)->string = stringcopy(clabel->string);
1294
(*nlabel)->num_params = 0;
1295
(*nlabel)->passed = NULL;
1297
(*nlabel)->pin = clabel->pin;
1333
labelcopy(*nlabel, clabel);
1302
1337
register objinstptr *ninst, cinst;
1304
1339
cinst = TOOBJINST(oldobj->plist + i);
1305
1340
NEW_OBJINST(ninst, (*newobj));
1306
(*ninst)->rotation = cinst->rotation;
1307
(*ninst)->color = cinst->color;
1308
(*ninst)->position.x = cinst->position.x;
1309
(*ninst)->position.y = cinst->position.y;
1310
(*ninst)->scale = cinst->scale;
1311
(*ninst)->thisobject = cinst->thisobject;
1312
(*ninst)->num_params = 0;
1313
(*ninst)->passed = NULL;
1315
/* Library instance's parameter list is always default (null) */
1316
(*ninst)->params = NULL;
1317
(*ninst)->bbox.lowerleft.x = cinst->thisobject->bbox.lowerleft.x;
1318
(*ninst)->bbox.lowerleft.y = cinst->thisobject->bbox.lowerleft.y;
1319
(*ninst)->bbox.width = cinst->thisobject->bbox.width;
1320
(*ninst)->bbox.height = cinst->thisobject->bbox.height;
1323
(*ninst)->schembbox = NULL;
1325
/* here---deal with attached schematics */
1341
instcopy(*ninst, cinst);
1329
1344
(*newobj)->parts++;
1345
1360
/* ButtonPress handler during normal catalog viewing mode */
1346
1361
/*--------------------------------------------------------*/
1348
void catbutton(u_int mode, XButtonEvent *event)
1363
void catalog_op(int op, int x, int y)
1350
1365
short *newselect;
1351
1366
objinstptr *newobject, *libobj;
1353
1368
short ocentx, ocenty, rangex, rangey, xdiff, ydiff, flag = 0;
1356
/* Make catbutton() a wrapper for pagecatbutton() */
1371
/* Make catalog_op() a wrapper for pagecat_op() */
1358
1373
if (is_library(topobject) < 0) {
1359
pagecatbutton(event);
1374
pagecat_op(op, x, y);
1363
if (event->button == Button1 || event->button == Button2) {
1365
window_to_user(event->x, event->y, &areastruct.save);
1378
/* If XCF_Cancel was invoked, return without a selection. */
1380
if (op == XCF_Cancel) {
1381
eventmode = NORMAL_MODE;
1386
window_to_user(x, y, &areastruct.save);
1367
1388
for (libobj = (objinstptr *)topobject->plist; libobj <
1368
1389
(objinstptr *)topobject->plist + topobject->parts; libobj++) {
1369
if ((*libobj)->type == OBJECT) {
1390
if (IS_OBJINST(*libobj)) {
1371
1392
ocentx = (*libobj)->position.x + (*libobj)->bbox.lowerleft.x
1372
1393
+ ((*libobj)->bbox.width >> 1);
1410
1428
/* retrieve drawing window state and set position of object to
1411
1429
be correct in reference to that window */
1413
snap(event->x, event->y, &oldpos);
1431
snap(x, y, &oldpos);
1415
1433
setpage(FALSE);
1417
snap(event->x, event->y, &areastruct.save);
1435
snap(x, y, &areastruct.save);
1418
1436
xdiff = areastruct.save.x - oldpos.x;
1419
1437
ydiff = areastruct.save.y - oldpos.y;
1453
1471
*newselect = (short)(newobject - (objinstptr *)topobject->plist);
1456
if ((void *)mode == (void *)(1)) {
1474
if (op == XCF_Library_Copy) {
1458
/* key "c" pressed for "copy" */
1476
/* Key "c" pressed for "copy" (default binding) */
1460
1478
XDefineCursor(dpy, areastruct.areawin, COPYCURSOR);
1461
eventmode = COPY2_MODE;
1479
eventmode = COPY_MODE;
1462
1480
#ifndef TCL_WRAPPER
1463
1481
xcAddEventHandler(areastruct.area, PointerMotionMask, False,
1464
(xcEventHandler)drag, NULL);
1482
(xcEventHandler)xlib_drag, NULL);
1468
eventmode = PRESS_MODE;
1486
eventmode = MOVE_MODE;
1487
areastruct.editcycle = 1;
1470
1489
#ifdef TCL_WRAPPER
1490
/* fprintf(stderr, "Creating event handler for xctk_drag: "); */
1491
/* printeventmode(); */
1471
1492
Tk_CreateEventHandler(areastruct.area, PointerMotionMask,
1472
1493
(Tk_EventProc *)xctk_drag, NULL);
1495
register_for_undo(XCF_Library_Pop, UNDO_MORE, areastruct.topinstance,
1496
areastruct.selectlist, areastruct.selects);
1477
/* If button2 was pressed, select and stay in the catalog. */
1478
/* Could just do "objectselect" here, but would not cover */
1500
/* Select the closest element and stay in the catalog. */
1501
/* Could just do "select_element" here, but would not cover */
1479
1502
/* the entire area in the directory surrounding the object. */
1504
else if (op == XCF_Select) {
1482
1505
short newinst = (short)(libobj - (objinstptr *)topobject->plist);
1483
1506
/* (ignore this object if it is already in the list of selects) */
1484
1507
for (newselect = areastruct.selectlist; newselect <
1541
1558
(areastruct.topinstance == xobjs.libtop[libmod])) return;
1543
1560
if (libmod == FONTLIB) {
1544
XDefineCursor (dpy, areastruct.areawin, CROSS);
1545
if (eventmode == TEXT2_MODE)
1561
XDefineCursor (dpy, areastruct.areawin, DEFAULTCURSOR);
1562
if (eventmode == TEXT_MODE)
1546
1563
eventmode = FONTCAT_MODE;
1548
eventmode = FONTCAT2_MODE;
1565
eventmode = EFONTCAT_MODE;
1551
1567
else if (eventmode == ASSOC_MODE) {
1552
XDefineCursor (dpy, areastruct.areawin, CROSS);
1568
XDefineCursor (dpy, areastruct.areawin, DEFAULTCURSOR);
1555
1570
else if (libmod == PAGELIB || libmod == LIBLIB) {
1556
XDefineCursor (dpy, areastruct.areawin, CROSS);
1571
XDefineCursor (dpy, areastruct.areawin, DEFAULTCURSOR);
1557
1572
eventmode = CATALOG_MODE;