60
63
short savedir = 0; /* for rhomboid/manhattan editing */
63
unsigned char texttype;
68
/*--------------------------------------*/
69
/* Element constructor functions */
70
/*--------------------------------------*/
72
/*--------------------------------------------------------------*/
73
/* Label constructor: Create a new label element in the object */
74
/* whose instance is "destinst" and return a pointer to it. */
76
/* "destinst" is the destination instance. If NULL, the */
77
/* top-level instance (areastruct.topinstance) is used. */
78
/* "strptr" is a pointer to a stringpart string, and may */
79
/* be NULL. If non-NULL, should NOT be free'd by the */
80
/* calling routine. */
81
/* "pintype" is NORMAL, LOCAL, GLOBAL, or INFO */
82
/* "x" and "y" are the label coordinates. */
84
/* Other properties must be set individually by the calling */
87
/* Return value is a pointer to the newly created label. */
88
/*--------------------------------------------------------------*/
90
labelptr new_label(objinstptr destinst, stringpart *strptr, int pintype,
95
objinstptr locdestinst;
97
locdestinst = (destinst == NULL) ? areastruct.topinstance : destinst;
98
destobject = locdestinst->thisobject;
100
NEW_LABEL(newlab, destobject);
102
labeldefaults(*newlab, pintype, x, y);
104
if (strptr->type == FONT_NAME) {
105
free ((*newlab)->string);
106
(*newlab)->string = strptr;
109
(*newlab)->string->nextpart = strptr;
111
calcbboxvalues(locdestinst, (genericptr *)newlab);
112
updatepagebounds(destobject);
113
incr_changes(destobject);
117
/*--------------------------------------------------------------*/
118
/* Variant of the above; creates a label from a (char *) string */
119
/* instead of a stringpart pointer. Like the stringpart */
120
/* pointer above, "cstr" should NOT be free'd by the calling */
122
/*--------------------------------------------------------------*/
124
labelptr new_simple_label(objinstptr destinst, char *cstr,
125
int pintype, int x, int y)
129
strptr = (stringpart *)malloc(sizeof(stringpart));
130
strptr->type = TEXT_STRING;
131
strptr->nextpart = NULL;
132
strptr->data.string = cstr;
134
return new_label(destinst, strptr, pintype, x, y);
137
/*--------------------------------------------------------------*/
138
/* Another variant of the above; creates a "temporary" label */
139
/* from a (char *) string. As above, "cstr" should NOT be */
140
/* free'd by the calling routine. The "temporary" label has no */
141
/* font information, and cannot be displayed nor saved/loaded */
142
/* from the PostScript output file. Used to name networks or */
143
/* to mark port positions. Pin type is always LOCAL. Does not */
144
/* require updating bounding box info since it cannot be */
145
/* displayed. Consequently, only requires passing the object */
146
/* to get the new label, not its instance. */
147
/*--------------------------------------------------------------*/
149
labelptr new_temporary_label(objectptr destobject, char *cstr,
154
NEW_LABEL(newlab, destobject);
156
labeldefaults(*newlab, LOCAL, x, y);
158
(*newlab)->string->type = TEXT_STRING; /* overwrites FONT record */
159
(*newlab)->string->data.string = cstr;
163
/*--------------------------------------------------------------*/
164
/* Polygon constructor: Create a new polygon element in the */
165
/* object whose instance is "destinst" and return a pointer to */
168
/* "destinst" is the destination instance. If NULL, the */
169
/* top-level instance (areastruct.topinstance) is used. */
170
/* "points" is a list of XPoint pointers, should not be */
171
/* NULL. It is transferred to the polygon verbatim, */
172
/* and should NOT be free'd by the calling routine. */
173
/* "number" is the number of points in the list, or zero */
174
/* if "points" is NULL. */
176
/* Other properties must be set individually by the calling */
179
/* Return value is a pointer to the newly created polygon. */
180
/*--------------------------------------------------------------*/
182
polyptr new_polygon(objinstptr destinst, pointlist *points, int number)
185
objectptr destobject;
186
objinstptr locdestinst;
188
locdestinst = (destinst == NULL) ? areastruct.topinstance : destinst;
189
destobject = locdestinst->thisobject;
191
NEW_POLY(newpoly, destobject);
193
polydefaults(*newpoly, 0, 0, 0);
194
(*newpoly)->number = number;
195
(*newpoly)->points = *points;
197
calcbboxvalues(locdestinst, (genericptr *)newpoly);
198
updatepagebounds(destobject);
199
incr_changes(destobject);
203
/*--------------------------------------------------------------*/
204
/* Spline constructor: Create a new spline element in the */
205
/* object whose instance is "destinst" and return a pointer to */
208
/* "destinst" is the destination instance. If NULL, the */
209
/* top-level instance (areastruct.topinstance) is used. */
210
/* "points" is a array of 4 XPoints; should not be NULL. */
212
/* Other properties must be set individually by the calling */
215
/* Return value is a pointer to the newly created spline. */
216
/*--------------------------------------------------------------*/
218
splineptr new_spline(objinstptr destinst, pointlist points)
220
splineptr *newspline;
221
objectptr destobject;
222
objinstptr locdestinst;
225
locdestinst = (destinst == NULL) ? areastruct.topinstance : destinst;
226
destobject = locdestinst->thisobject;
228
NEW_SPLINE(newspline, destobject);
230
splinedefaults(*newspline, 0, 0);
232
for (i = 0; i < 4; i++)
233
(*newspline)->ctrl[i] = points[i];
235
calcspline(*newspline);
236
calcbboxvalues(locdestinst, (genericptr *)newspline);
237
updatepagebounds(destobject);
238
incr_changes(destobject);
242
/*--------------------------------------------------------------*/
243
/* Arc constructor: Create a new arc element in the object */
244
/* whose instance is "destinst" and return a pointer to it. */
246
/* "destinst" is the destination instance. If NULL, the */
247
/* top-level instance (areastruct.topinstance) is used. */
248
/* "radius" is the radius of the (circular) arc. */
249
/* "x" and "y" represents the arc center position. */
251
/* Other properties must be set individually by the calling */
254
/* Return value is a pointer to the newly created arc. */
255
/*--------------------------------------------------------------*/
257
arcptr new_arc(objinstptr destinst, int radius, int x, int y)
260
objectptr destobject;
261
objinstptr locdestinst;
263
locdestinst = (destinst == NULL) ? areastruct.topinstance : destinst;
264
destobject = locdestinst->thisobject;
266
NEW_ARC(newarc, destobject);
268
arcdefaults(*newarc, x, y);
269
(*newarc)->radius = (*newarc)->yaxis = radius;
272
calcbboxvalues(locdestinst, (genericptr *)newarc);
273
updatepagebounds(destobject);
274
incr_changes(destobject);
278
/*--------------------------------------------------------------*/
279
/* Instance constructor: Create a new object instance element */
280
/* in the object whose instance is "destinst" and return a */
283
/* "destinst" is the destination instance. If NULL, the */
284
/* top-level instance (areastruct.topinstance) is used. */
285
/* "srcinst" is the source instance of which this is a */
287
/* "x" and "y" represents the instance position. */
289
/* Other properties must be set individually by the calling */
292
/* Return value is a pointer to the newly created arc. */
293
/*--------------------------------------------------------------*/
295
objinstptr new_objinst(objinstptr destinst, objinstptr srcinst, int x, int y)
297
objinstptr *newobjinst;
298
objectptr destobject;
299
objinstptr locdestinst;
301
locdestinst = (destinst == NULL) ? areastruct.topinstance : destinst;
302
destobject = locdestinst->thisobject;
304
NEW_OBJINST(newobjinst, destobject);
306
instcopy(*newobjinst, srcinst);
307
(*newobjinst)->position.x = x;
308
(*newobjinst)->position.y = y;
310
calcbboxvalues(locdestinst, (genericptr *)newobjinst);
311
updatepagebounds(destobject);
312
incr_changes(destobject);
316
/*--------------------------------------------------------------*/
317
/* Generic element destructor function */
318
/*--------------------------------------------------------------*/
320
void remove_element(objinstptr destinst, genericptr genelem)
322
objectptr destobject;
323
objinstptr locdestinst;
325
locdestinst = (destinst == NULL) ? areastruct.topinstance : destinst;
326
destobject = locdestinst->thisobject;
328
genelem->type &= REMOVE_TAG;
329
delete_tagged(destobject);
330
calcbboxvalues(locdestinst, (genericptr *)NULL);
331
updatepagebounds(destobject);
65
334
/*-------------------------------------*/
66
335
/* Sane values for a new path instance */
300
542
UDrawTLine(curlabel);
302
if (isbound(keypressed, XCF_Text_Delete) && textpos > 1) {
306
if (textend == 0) textend = textpos - 1;
308
undrawtext(curlabel);
309
for (strpos = textpos - 1; strpos >= textend; strpos--) {
310
strptr = findstringpart(strpos, &curloc, curlabel->string,
544
if (r = isbound(keypressed, XCF_Text_Delete)) {
549
if (textend == 0) textend = textpos - 1;
551
undrawtext(curlabel);
552
for (strpos = textpos - 1; strpos >= textend; strpos--) {
553
strptr = findstringpart(strpos, &curloc, curlabel->string,
311
554
areastruct.topinstance);
313
memmove(strptr->data.string + curloc,
556
memmove(strptr->data.string + curloc,
314
557
strptr->data.string + curloc + 1,
315
558
strlen(strptr->data.string + curloc + 1) + 1);
316
if (strlen(strptr->data.string) == 0)
317
deletestring(strptr, &curlabel->string, areastruct.topinstance);
320
/* Don't delete any parameter boundaries---must use */
321
/* "unparameterize" command for that. */
323
else if (strptr != NULL) {
324
if ((strptr->type != PARAM_START) && (strptr->type != PARAM_END))
325
deletestring(strptr, &curlabel->string, areastruct.topinstance);
559
if (strlen(strptr->data.string) == 0)
560
deletestring(strptr, &curlabel->string, areastruct.topinstance);
563
/* Don't delete any parameter boundaries---must use */
564
/* "unparameterize" command for that. */
566
else if (strptr != NULL) {
567
if ((strptr->type != PARAM_START) && (strptr->type != PARAM_END))
568
deletestring(strptr, &curlabel->string, areastruct.topinstance);
573
Fprintf(stdout, "Error: Unexpected NULL string part\n");
580
else if (r = isbound(keypressed, XCF_Text_Delete_Param)) {
585
strptr = findstringpart(textpos - 1, &curloc, curlabel->string,
586
areastruct.topinstance);
587
if ((curloc < 0) && (strptr != NULL) && (strptr->type == PARAM_END)) {
588
undrawtext(curlabel);
589
while (strptr->type != PARAM_START)
590
strptr = findstringpart(--strpos, &curloc, curlabel->string,
591
areastruct.topinstance);
592
unmakeparam(curlabel, strptr);
330
Fprintf(stdout, "Error: Unexpected NULL string part\n");
336
else if (isbound(keypressed, XCF_Text_Return)) {
597
else if (r = isbound(keypressed, XCF_Text_Return)) {
337
598
Boolean hasstuff = False; /* Check for null string */
338
Boolean do_all = True;
339
599
stringpart *tmppos;
341
601
for (tmppos = curlabel->string; tmppos != NULL; tmppos = tmppos->nextpart) {
342
602
if (tmppos->type == PARAM_START) hasstuff = True;
343
603
else if (tmppos->type == TEXT_STRING) hasstuff = True;
345
XDefineCursor(dpy, areastruct.areawin, CROSS);
605
XDefineCursor(dpy, areastruct.areawin, DEFAULTCURSOR);
349
if (hasstuff && (eventmode != TEXT3_MODE && eventmode != CATTEXT_MODE)) {
609
if (hasstuff && (eventmode != ETEXT_MODE && eventmode != CATTEXT_MODE)) {
350
610
topobject->parts++;
611
register_for_undo(XCF_Text, UNDO_DONE, areastruct.topinstance,
351
614
incr_changes(topobject);
353
topobject->valid = False;
357
else if (!hasstuff && (eventmode == TEXT3_MODE)) topobject->parts--;
615
invalidate_netlist(topobject);
618
else if (!hasstuff && (eventmode == ETEXT_MODE)) {
619
if (areastruct.editpart < topobject->parts) {
620
short *sptr = allocselect();
621
*sptr = areastruct.editpart;
623
/* Force the "delete" undo record to be a continuation of */
624
/* the undo series containing the edit. That way, "undo" */
625
/* does not generate a label with null text. */
627
xobjs.undostack->idx = -xobjs.undostack->idx;
628
standard_element_delete(NORMAL);
631
/* Label had just been created; just delete it w/o undo */
632
freelabel(curlabel->string);
359
638
if ((!hasstuff) && (eventmode == CATTEXT_MODE)) { /* can't have null labels! */
360
freelabel(curlabel->string);
361
curlabel->string = stringcopyback(labelbuf, areastruct.topinstance);
364
resolveparams(areastruct.topinstance);
365
640
XcSetFunction(GXcopy);
366
641
redrawtext(curlabel);
367
642
Wprintf("Object must have a name!");
368
643
eventmode = CATALOG_MODE;
370
645
else if (!hasstuff) {
371
freelabel(curlabel->string);
373
646
eventmode = NORMAL_MODE;
375
648
else if (eventmode == CATTEXT_MODE) {
377
/* set name of object to new string */
379
areastruct.save.y = curlabel->position.y + 100;
380
areastruct.save.x = curlabel->position.x;
381
objectselect(OBJECT);
382
if (areastruct.selects == 1) { /* this should be true! */
383
short *selptr = areastruct.selectlist + areastruct.selects - 1;
384
objinstptr selobj = SELTOOBJINST(selptr);
385
strcpy(selobj->thisobject->name, curlabel->string->nextpart->data.string);
652
/* Get the library object whose name matches the original string */
653
oldname = get_original_string(curlabel);
654
libobj = NameToObject(oldname->nextpart->data.string, NULL, FALSE);
655
if (libobj != NULL) {
657
/* set name of object to new string */
659
strcpy(libobj->name, curlabel->string->nextpart->data.string);
386
661
/* If checkname() alters the name, it has to be copied back to */
387
662
/* the catalog label for the object. */
389
if (checkname(selobj->thisobject)) {
664
if (checkname(libobj)) {
390
665
undrawtext(curlabel);
391
666
curlabel->string->nextpart->data.string = (char *)realloc(
392
667
curlabel->string->nextpart->data.string,
393
668
(strlen(_STR) + 1) * sizeof(char));
394
strcpy(curlabel->string->nextpart->data.string,
395
selobj->thisobject->name);
669
strcpy(curlabel->string->nextpart->data.string, libobj->name);
396
670
XcSetFunction(GXcopy);
397
671
redrawtext(curlabel);
400
674
eventmode = CATALOG_MODE;
403
677
else { /* (hasstuff && eventmode != CATTEXT_MODE) */
404
678
eventmode = NORMAL_MODE;
405
679
incr_changes(topobject);
407
if (curlabel->pin != False) topobject->valid = False;
680
if (curlabel->pin != False) invalidate_netlist(topobject);
411
683
setdefaultfontmarks();
412
684
setcolormark(areastruct.color);
413
if (labelbuf != NULL) {
685
if ((labelbuf = get_original_string(curlabel)) != NULL) {
416
687
/* If the original label (before modification) is a pin in a */
417
688
/* schematic/symbol with a matching symbol/schematic, and the */
418
689
/* name is unique, change every pin in the matching symbol/ */
419
690
/* schematic to match the new text. */
421
if ((areastruct.schemon == True) && (curlabel->pin != False) &&
692
if ((areastruct.schemon == True) && (curlabel->pin == LOCAL) &&
422
693
(topobject->symschem != NULL)) {
423
694
if ((findlabelcopy(curlabel, labelbuf) == NULL)
424
695
&& (findlabelcopy(curlabel, curlabel->string) == NULL)) {
425
696
changeotherpins(curlabel, labelbuf);
426
if (topobject->schemtype == SCHEMATIC)
697
if (topobject->schemtype == PRIMARY || topobject->schemtype == SECONDARY)
427
698
Wprintf("Changed corresponding pin in associated symbol");
429
700
Wprintf("Changed corresponding pin in associated schematic");
430
701
incr_changes(topobject->symschem);
431
topobject->symschem->valid = False;
702
invalidate_netlist(topobject->symschem);
438
706
resolveparams(areastruct.topinstance);
440
updateinstparam(areastruct.topinstance, do_all);
441
else /* do_all == -1 */
442
calcbbox(areastruct.topinstance);
707
updateinstparam(topobject);
444
708
setobjecttype(topobject);
448
711
calcbbox(areastruct.topinstance);
451
else if (isbound(keypressed, XCF_Text_Right) && curpos != NULL)
453
else if (isbound(keypressed, XCF_Text_Left) && textpos > 1)
455
else if (isbound(keypressed, XCF_Text_Down)) {
715
else if (r = isbound(keypressed, XCF_Text_Right)) {
716
if (curpos != NULL) textpos++;
718
else if (r = isbound(keypressed, XCF_Text_Left)) {
719
if (textpos > 1) textpos--;
721
else if (r = isbound(keypressed, XCF_Text_Down)) {
456
722
while (curpos != NULL) {
458
724
curpos = findstringpart(textpos, &locpos, curlabel->string,