38
37
/* Externally declared global variables */
39
38
/*----------------------------------------------------------------------*/
41
extern Tcl_Interp *xcinterp;
41
43
extern Globaldata xobjs;
42
44
extern Clientdata areastruct;
43
45
extern Widget menuwidgets[];
44
extern objectpair *pushlist;
45
46
extern short textpos, textend;
46
47
extern char _STR[150];
50
51
/* types which are able to accept the given parameterization. */
51
52
/*----------------------------------------------------------------------*/
53
static u_char param_select[] = {
54
u_char param_select[] = {
54
55
POLYGON | SPLINE | LABEL | OBJECT | ARC, /* P_POSITION */
55
56
LABEL, /* P_SUBSTRING */
56
57
POLYGON | SPLINE | LABEL | OBJECT | ARC, /* P_POSITION_X */
67
68
SEL_ANY /* P_COLOR (tbd) */
72
xcWidget *param_buttons[] = {
73
/* To be done---map buttons to Tk_Windows! */
70
76
Widget *param_buttons[] = {
71
77
&ParametersPositionButton, /* P_POSITION */
72
78
&ParametersSubstringButton, /* P_SUBSTRING */
97
104
for (i = 0; i < thiselem->num_params; i++) {
98
105
j = thiselem->passed[i].paramno;
99
106
k = thiselem->passed[i].pointno;
100
ops = objectdata->params[j];
107
ops = topobject->params[j];
101
108
switch(ops->which) {
102
109
case P_POSITION: case P_POSITION_X: case P_POSITION_Y:
103
110
switch(thiselem->type) {
132
138
/* pgen = NULL returns menu to default settings */
133
139
/*----------------------------------------------*/
142
void setparammarks(genericptr thiselem)
144
/* Set GUI variables associated with the "parameter" menu. */
149
/* These match the order of parameter definitions in xcircuit.h */
150
const char *paramvars[] = {"positionparam", "substringparam", "xparam",
151
"yparam", "styleparam", "justparam", "startparam", "endparam",
152
"radiusparam", "minorparam", "rotationparam", "scaleparam",
153
"linewidthparam", "colorparam"};
155
/* Reset all variables to false */
156
for (i = 0; i < 14; i++)
157
Tcl_SetVar(xcinterp, (char *)paramvars[i], "false", TCL_NAMESPACE_ONLY);
159
/* For each parameter declared, set the corresponding Tcl variable */
160
if (thiselem != NULL) {
161
for (i = 0; i < thiselem->num_params; i++) {
162
j = thiselem->passed[i].paramno;
163
ops = topobject->params[j];
164
Tcl_SetVar(xcinterp, (char *)paramvars[ops->which], "true",
135
171
void setparammarks(genericptr thiselem)
139
const int rlength = sizeof(param_buttons) / sizeof(int);
175
const int rlength = sizeof(param_buttons) / sizeof(Widget *);
140
176
int i, j, paramno;
152
188
if (thiselem != NULL) {
153
189
for (i = 0; i < thiselem->num_params; i++) {
154
190
j = thiselem->passed[i].paramno;
155
ops = objectdata->params[j];
191
ops = topobject->params[j];
156
192
w = *param_buttons[ops->which];
157
193
XtSetArg(wargs[0], XtNsetMark, True);
158
194
XtSetValues(w, wargs, 1);
384
422
objinstptr pinst;
385
423
objectptr thisobj;
387
pinst = (thisinst == areastruct.topobject) ? NORMINST : thisinst;
425
pinst = (thisinst == areastruct.topinstance) ? areastruct.topinstance : thisinst;
388
426
if (pinst == NULL) return -1; /* there is no instance */
389
else if (pinst->params == NULL) return -1; /* instance has no parameters */
427
else if (pinst->thisobject->params == NULL)
428
return -1; /* object has no parameters */
391
thisobj = (pinst == NULL) ? objectdata : pinst->thisobject;
430
thisobj = (pinst == NULL) ? topobject : pinst->thisobject;
392
431
return opsubstitute(thisobj, pinst);
434
/*----------------------------------------------*/
435
/* Check if an element contains a parameter. */
436
/*----------------------------------------------*/
438
Boolean has_param(genericptr celem)
440
if (celem->type == LABEL) {
442
labelptr clab = (labelptr)celem;
443
for (cstr = clab->string; cstr != NULL; cstr = cstr->nextpart)
444
if (cstr->type == PARAM_START)
447
if (celem->num_params > 0) return TRUE;
395
451
/*------------------------------------------------------*/
396
452
/* Find "current working values" in the element list of */
397
453
/* an object, and write them into the instance's */
415
pinst = (thisinst == areastruct.topobject) ? NORMINST : thisinst;
416
thisobj = (pinst == NULL) ? objectdata : pinst->thisobject;
471
pinst = (thisinst == areastruct.topinstance) ? areastruct.topinstance : thisinst;
472
thisobj = (pinst == NULL) ? topobject : pinst->thisobject;
418
474
/* make sure that all instance values exist */
419
475
if (pinst != NULL) copyparams(pinst, pinst);
646
702
/* If the object was pushed into from a library, we want to change */
647
703
/* the default, not the instanced, parameter values. However, this */
648
/* is not true for "virtual" library objects (in the speclist) */
704
/* is not true for "virtual" library objects (in the instlist) */
650
706
if ((i = checklibtop()) >= 0) {
651
for (spec = xobjs.userlibs[i].speclist; spec != NULL;
652
spec = spec->nextpair)
707
for (spec = xobjs.userlibs[i].instlist; spec != NULL;
653
709
if (spec->thisinst == thisinst)
657
/* printf("Came from library or top page: changing default value\n"); */
712
if ((spec == NULL) || (spec->virtual == FALSE)) {
713
/* Fprintf(stdout, "Came from library or top page: "
714
"changing default value\n"); */
658
715
replaceparams(thisinst);
773
836
/* cannot form a parameter on a top-level page */
774
if (is_page(objectdata) != -1) {
837
if (is_page(topobject) != -1) {
775
838
Wprintf("Cannot form a parameter in a top-level page!");
779
if (objectdata->params == NULL) {
780
objectdata->num_params = 1;
781
objectdata->params = (oparamptr *)malloc(sizeof(oparamptr));
842
/* Make sure the parameter doesn't already exist. */
844
if ((*gelem)->num_params > 0) {
845
for (epp = (*gelem)->passed; epp < (*gelem)->passed
846
+ (*gelem)->num_params; epp++) {
847
ops = *(topobject->params + epp->paramno);
848
if (ops->which == (u_char)mode) {
849
Fprintf(stderr, "Cannot duplicate a parameter!\n");
855
if (topobject->params == NULL) {
856
topobject->num_params = 1;
857
topobject->params = (oparamptr *)malloc(sizeof(oparamptr));
784
objectdata->num_params++;
785
objectdata->params = (oparamptr *)realloc(objectdata->params,
786
objectdata->num_params * sizeof(oparamptr));
860
topobject->num_params++;
861
topobject->params = (oparamptr *)realloc(topobject->params,
862
topobject->num_params * sizeof(oparamptr));
788
*(objectdata->params + objectdata->num_params - 1) = (oparamptr)
864
*(topobject->params + topobject->num_params - 1) = (oparamptr)
789
865
malloc(sizeof(oparam));
791
initallinstances(objectdata, objectdata->num_params - 1);
867
initallinstances(topobject, topobject->num_params - 1);
793
ops = *(objectdata->params + objectdata->num_params - 1);
869
ops = *(topobject->params + topobject->num_params - 1);
794
870
ops->type = XC_INT; /* most commonly used value */
795
871
ops->which = (u_char)mode; /* what kind of parameter */
961
1039
short i, nparms = 0;
1040
int result, selparm = -1;
964
1042
/* Don't allow nested parameters */
966
1044
tlab = TOLABEL(EDITPART);
967
if (paramcross(objectdata, tlab)) {
1045
if (paramcross(topobject, tlab)) {
968
1046
Wprintf("Parameters cannot be nested!");
973
1051
/* If only one, then automatically use it. Otherwise, prompt */
974
1052
/* for which parameter to use. */
976
for (i = 0; i < objectdata->num_params; i++) {
977
ops = *(objectdata->params + i);
1054
for (i = 0; i < topobject->num_params; i++) {
1055
ops = *(topobject->params + i);
978
1056
if (ops->type == XC_STRING) {
983
1061
if (nparms > 1) {
984
1062
char *newstr, *sptr;
985
1063
char *sstart = (char *)malloc(250);
1064
u_char *parammap = (u_char *)malloc(nparms);
987
1066
strcpy(sstart, "Choose: ");
988
1067
sptr = sstart + 8;
989
for (i = 0; i < objectdata->num_params; i++) {
990
ops = *(objectdata->params + i);
1068
for (i = 0; i < topobject->num_params; i++) {
1069
ops = *(topobject->params + i);
991
1070
if (ops->type == XC_STRING) {
1071
parammap[nparms] = i;
993
1073
if (nparms != 1) {
994
1074
strcat(sptr, ", ");
1005
1085
Wprintf(sstart);
1008
/* This is a bit quirky; but works for now. Later, would prefer */
1009
/* a GUI-oriented selection mechanism. */
1010
selparm = getkeynum();
1090
/* The Tcl version uses a GUI selection mechanism. */
1092
result = Tcl_Eval(xcinterp, "xcircuit::promptselectparam");
1093
if (result != TCL_OK) {
1094
Tcl_SetResult(xcinterp, "Error in executing promptselectparam", NULL);
1097
result = Tcl_GetIntFromObj(xcinterp, Tcl_GetObjResult(xcinterp), &selparm);
1098
if (result != TCL_OK) {
1099
Tcl_SetResult(xcinterp, "Bad parameter number.", NULL);
1102
/* Relate index in list (string parameters only) to index */
1103
/* over all parameters. */
1105
if (selparm >= 0) selparm = parammap[selparm];
1107
/* The non-Tcl version is a bit quirky, but it works. */
1109
selparm = parammap[getkeynum()];
1013
if ((selparm >= 0) && (selparm < objectdata->num_params))
1114
if ((selparm >= 0) && (selparm < topobject->num_params))
1014
1115
labeltext(PARAM_START, (char *)&selparm);
1016
1117
Wprintf("Parameter number nonexistent.");
1028
1129
/* cannot form a parameter on a top-level page */
1030
if (is_page(objectdata) != -1) {
1131
if (is_page(topobject) != -1) {
1031
1132
Wprintf("Cannot form a parameter in a top-level page!");
1035
1136
/* make sure this does not overlap another parameter */
1037
if (paramcross(objectdata, thislabel)) {
1138
if (paramcross(topobject, thislabel)) {
1038
1139
Wprintf("Parameters cannot be nested!");
1044
1145
/* intended parameter boundaries */
1046
1147
if (textend > 0 && textend < textpos) { /* partial string */
1047
begpart = splitstring(textend, &thislabel->string, NULL);
1048
endpart = splitstring(textpos, &thislabel->string, NULL);
1148
begpart = splitstring(textend, &thislabel->string, areastruct.topinstance);
1149
endpart = splitstring(textpos, &thislabel->string, areastruct.topinstance);
1050
1151
/* note that "partial string" may overlap the beginning */
1051
1152
/* or the end, so deal with these instances. */
1061
1162
endpart = makesegment(&thislabel->string, NULL);
1063
1164
begpart->type = PARAM_START;
1064
begpart->data.paramno = (objectdata->params == NULL) ? 0 :
1065
objectdata->num_params;
1165
begpart->data.paramno = (topobject->params == NULL) ? 0 :
1166
topobject->num_params;
1066
1167
endpart->type = PARAM_END;
1068
1169
/* Now move the sections of string to the object parameter */
1070
if (objectdata->params == NULL) {
1071
objectdata->num_params = 1;
1072
objectdata->params = (oparamptr *)malloc(sizeof(oparamptr));
1171
if (topobject->params == NULL) {
1172
topobject->num_params = 1;
1173
topobject->params = (oparamptr *)malloc(sizeof(oparamptr));
1075
objectdata->num_params++;
1076
objectdata->params = (oparamptr *)realloc(objectdata->params,
1077
objectdata->num_params * sizeof(oparamptr));
1176
topobject->num_params++;
1177
topobject->params = (oparamptr *)realloc(topobject->params,
1178
topobject->num_params * sizeof(oparamptr));
1079
1180
/* We have added a parameter. This requires that all instances */
1080
1181
/* of the object which do not have NULL params must initialize */
1081
1182
/* and NULL the pointer to the new parameter. */
1083
initallinstances(objectdata, objectdata->num_params - 1);
1184
initallinstances(topobject, topobject->num_params - 1);
1085
*(objectdata->params + objectdata->num_params - 1) = (oparamptr)
1186
*(topobject->params + topobject->num_params - 1) = (oparamptr)
1086
1187
malloc(sizeof(oparam));
1089
ops = *(objectdata->params + objectdata->num_params - 1);
1190
ops = *(topobject->params + topobject->num_params - 1);
1090
1191
ops->type = XC_STRING;
1192
ops->which = P_SUBSTRING;
1091
1193
ops->parameter.string = begpart->nextpart;
1092
1194
begpart->nextpart = endpart->nextpart;
1093
1195
endpart->nextpart = NULL;
1198
incr_changes(topobject);
1098
1201
/*------------------------------------------------------*/
1111
1214
tinst = TOOBJINST(pgen);
1112
1215
if (tinst->thisobject == refobj) {
1113
1216
if (tinst->params != NULL) {
1217
/* Make sure we've allocated enough space for this parameter */
1218
tinst->params = (oparamptr *)realloc(tinst->params,
1219
tinst->thisobject->num_params * sizeof(oparamptr));
1114
1220
*(tinst->params + pnum) = NULL;
1181
1287
for (k = 0; k < xobjs.pages; k++) {
1182
initinst(xobjs.pagelist[k]->pageobj, thisobj, p);
1288
if (xobjs.pagelist[k]->pageinst != NULL)
1289
initinst(xobjs.pagelist[k]->pageinst->thisobject, thisobj, p);
1184
1291
for (j = 0; j < xobjs.numlibs; j++) {
1185
1292
for (k = 0; k < xobjs.userlibs[j].number; k++) {
1186
1293
initinst(*(xobjs.userlibs[j].library + k), thisobj, p);
1295
initinst(xobjs.libtop[LIBRARY + j]->thisobject, thisobj, p);
1189
1297
for (k = 0; k < xobjs.delbuffer.number; k++) {
1190
1298
initinst(*(xobjs.delbuffer.library + k), thisobj, p);
1234
1342
/* instance of the parameter. Otherwise, we delete the parameter */
1235
1343
/* and also remove it from the parameters list. */
1237
for (pgen = objectdata->plist; pgen < objectdata->plist + objectdata->parts;
1345
for (pgen = topobject->plist; pgen < topobject->plist + topobject->parts;
1239
1347
if ((*pgen)->type == LABEL) {
1240
1348
plab = TOLABEL(pgen);
1290
1398
/* substitutions which may have been made. */
1292
1400
for (k = 0; k < xobjs.pages; k++) {
1293
searchinst(xobjs.pagelist[k]->pageobj, objectdata, p);
1401
if (xobjs.pagelist[k]->pageinst != NULL)
1402
searchinst(xobjs.pagelist[k]->pageinst->thisobject, topobject, p);
1295
1404
for (j = 0; j < xobjs.numlibs; j++) {
1296
1405
for (k = 0; k < xobjs.userlibs[j].number; k++) {
1297
if (*(xobjs.userlibs[j].library + k) == objectdata)
1406
if (*(xobjs.userlibs[j].library + k) == topobject)
1300
searchinst(*(xobjs.userlibs[j].library + k), objectdata, p);
1409
searchinst(*(xobjs.userlibs[j].library + k), topobject, p);
1303
1412
for (k = 0; k < xobjs.delbuffer.number; k++) {
1304
searchinst(*(xobjs.delbuffer.library + k), objectdata, p);
1413
searchinst(*(xobjs.delbuffer.library + k), topobject, p);
1307
/* Also check through any "virtual" instances on the library page */
1416
/* Also check through all instances on the library page */
1309
for (spec = xobjs.userlibs[l].speclist; spec != NULL; spec = spec->nextpair)
1310
destroyinst(spec->thisinst, objectdata, p);
1418
for (spec = xobjs.userlibs[l].instlist; spec != NULL; spec = spec->next)
1419
destroyinst(spec->thisinst, topobject, p);
1314
1423
/* Re-order the remaining parameters */
1316
for (k = p; k < objectdata->num_params - 1; k++)
1317
*(objectdata->params + k) = *(objectdata->params + k + 1);
1425
for (k = p; k < topobject->num_params - 1; k++)
1426
*(topobject->params + k) = *(topobject->params + k + 1);
1319
1428
/* Decrement the number of parameters */
1321
if (--objectdata->num_params == 0) {
1322
free(objectdata->params);
1323
objectdata->params = NULL;
1430
if (--topobject->num_params == 0) {
1431
free(topobject->params);
1432
topobject->params = NULL;
1326
1435
/* decrement the parameter ID number of all parameters in all strings */
1327
1436
/* of this object whose parameter IDs are greater. */
1329
for (pgen = objectdata->plist; pgen < objectdata->plist + objectdata->parts;
1438
for (pgen = topobject->plist; pgen < topobject->plist + topobject->parts;
1331
1440
if ((*pgen)->type == LABEL) {
1332
1441
plab = TOLABEL(pgen);
1363
1473
&& textend < textpos) {
1364
1474
if (SELECTTYPE(areastruct.selectlist) != LABEL) return; /* Not a label */
1365
1475
settext = SELTOLABEL(areastruct.selectlist);
1366
strptr = findstringpart(textend, &locpos, settext->string, NORMINST);
1476
strptr = findstringpart(textend, &locpos, settext->string, areastruct.topinstance);
1367
1477
while (strptr != NULL && strptr->type != PARAM_END)
1368
1478
strptr = strptr->nextpart;
1369
1479
if (strptr == NULL) return; /* No parameters */
1374
1484
/* the whole parameter or the parameter start marker. */
1376
1486
for (tmpptr = settext->string; tmpptr != NULL && tmpptr != strptr;
1377
tmpptr = nextstringpart(tmpptr, NORMINST))
1487
tmpptr = nextstringpart(tmpptr, areastruct.topinstance))
1378
1488
if (tmpptr->type == PARAM_START) lastptr = tmpptr;
1379
1489
/* Finish search, unlinking any parameter we might be inside */
1380
for (; tmpptr != NULL; tmpptr = nextstringpart(tmpptr, NORMINST));
1490
for (; tmpptr != NULL; tmpptr = nextstringpart(tmpptr, areastruct.topinstance));
1382
1492
if (lastptr != NULL) unmakeparam(settext, lastptr);
1392
1502
if (strptr != NULL) unmakeparam(settext, strptr);
1394
1504
else if (mode == P_POSITION) {
1395
unmakenumericalp(objectdata->plist + (*fselect), P_POSITION_X);
1396
unmakenumericalp(objectdata->plist + (*fselect), P_POSITION_Y);
1505
unmakenumericalp(topobject->plist + (*fselect), P_POSITION_X);
1506
unmakenumericalp(topobject->plist + (*fselect), P_POSITION_Y);
1399
unmakenumericalp(objectdata->plist + (*fselect), mode);
1509
unmakenumericalp(topobject->plist + (*fselect), mode);
1511
setparammarks(NULL);
1426
1537
makeparam(settext);
1428
1539
else if (mode == P_POSITION) {
1429
makenumericalp(objectdata->plist + (*fselect), P_POSITION_X);
1430
makenumericalp(objectdata->plist + (*fselect), P_POSITION_Y);
1540
makenumericalp(topobject->plist + (*fselect), P_POSITION_X);
1541
makenumericalp(topobject->plist + (*fselect), P_POSITION_Y);
1433
makenumericalp(objectdata->plist + (*fselect), mode);
1544
makenumericalp(topobject->plist + (*fselect), mode);
1435
1546
objectdeselect();
1547
setparammarks(NULL);
1438
1550
/*----------------------------------------------------------------------*/
1445
1557
stringpart *firstptr, *lastptr;
1448
lastptr = findstringpart(textpos, &locpos, tlab->string, NORMINST);
1560
lastptr = findstringpart(textpos, &locpos, tlab->string, areastruct.topinstance);
1450
1562
/* This text position can't be inside another parameter */
1451
1563
for (firstptr = lastptr; firstptr != NULL; firstptr = firstptr->nextpart)
1454
1566
/* The area between textend and textpos cannot contain a parameter */
1455
1567
if (textend > 0)
1456
for (firstptr = findstringpart(textend, &locpos, tlab->string, NORMINST);
1457
firstptr != lastptr; firstptr = firstptr->nextpart)
1568
for (firstptr = findstringpart(textend, &locpos, tlab->string,
1569
areastruct.topinstance); firstptr != lastptr;
1570
firstptr = firstptr->nextpart)
1458
1571
if (firstptr->type == PARAM_START || firstptr->type == PARAM_END)
1468
1581
int checklibtop()
1472
objectpair *thispush = pushlist;
1474
while (thispush != NULL) {
1475
pobj = thispush->thisobject;
1476
if ((i = is_library(pobj)) >= 0) return i;
1477
thispush = thispush->nextpair;
1584
pushlistptr thispush;
1586
for (thispush = areastruct.stack; thispush != NULL; thispush = thispush->next)
1587
if ((i = is_library(thispush->thisinst->thisobject)) >= 0)