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

« back to all changes in this revision

Viewing changes to elements.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
 
 
14
#ifndef XC_WIN32
14
15
#include <X11/Intrinsic.h>
15
16
#include <X11/StringDefs.h>
 
17
#endif
16
18
 
17
19
#ifdef TCL_WRAPPER 
18
20
#include <tk.h>
19
21
#else
 
22
#ifndef XC_WIN32
20
23
#include "Xw/Xw.h"
21
24
#endif
 
25
#endif
22
26
 
23
27
/*----------------------------------------------------------------------*/
24
28
/* Local includes                                                       */
48
52
extern short fontcount;
49
53
extern short attachto;
50
54
extern char  _STR[150], _STR2[250];
51
 
extern stringpart *labelbuf;
52
55
extern int number_colors;
53
56
 
54
57
extern double atan2();
60
63
short savedir = 0;      /* for rhomboid/manhattan editing */
61
64
char extchar[20];
62
65
double saveratio;
63
 
unsigned char texttype;
 
66
u_char texttype;
 
67
 
 
68
/*--------------------------------------*/
 
69
/* Element constructor functions        */
 
70
/*--------------------------------------*/
 
71
 
 
72
/*--------------------------------------------------------------*/
 
73
/* Label constructor:  Create a new label element in the object */
 
74
/* whose instance is "destinst" and return a pointer to it.     */
 
75
/*                                                              */
 
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.                  */
 
83
/*                                                              */
 
84
/* Other properties must be set individually by the calling     */
 
85
/*      routine.                                                */
 
86
/*                                                              */
 
87
/* Return value is a pointer to the newly created label.        */
 
88
/*--------------------------------------------------------------*/
 
89
 
 
90
labelptr new_label(objinstptr destinst, stringpart *strptr, int pintype,
 
91
        int x, int y)
 
92
{
 
93
   labelptr *newlab;
 
94
   objectptr destobject;
 
95
   objinstptr locdestinst;
 
96
 
 
97
   locdestinst = (destinst == NULL) ? areastruct.topinstance : destinst;
 
98
   destobject = locdestinst->thisobject;
 
99
 
 
100
   NEW_LABEL(newlab, destobject);
 
101
   destobject->parts++;
 
102
   labeldefaults(*newlab, pintype, x, y);
 
103
 
 
104
   if (strptr->type == FONT_NAME) {
 
105
      free ((*newlab)->string);
 
106
      (*newlab)->string = strptr;
 
107
   }
 
108
   else
 
109
      (*newlab)->string->nextpart = strptr;
 
110
 
 
111
   calcbboxvalues(locdestinst, (genericptr *)newlab);
 
112
   updatepagebounds(destobject);
 
113
   incr_changes(destobject);
 
114
   return *newlab;
 
115
}
 
116
 
 
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    */
 
121
/* routine.                                                     */
 
122
/*--------------------------------------------------------------*/
 
123
 
 
124
labelptr new_simple_label(objinstptr destinst, char *cstr,
 
125
        int pintype, int x, int y)
 
126
{
 
127
   stringpart *strptr;
 
128
 
 
129
   strptr = (stringpart *)malloc(sizeof(stringpart));
 
130
   strptr->type = TEXT_STRING;
 
131
   strptr->nextpart = NULL;
 
132
   strptr->data.string = cstr;
 
133
 
 
134
   return new_label(destinst, strptr, pintype, x, y);
 
135
}
 
136
 
 
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
/*--------------------------------------------------------------*/
 
148
 
 
149
labelptr new_temporary_label(objectptr destobject, char *cstr,
 
150
        int x, int y)
 
151
{
 
152
   labelptr *newlab;
 
153
 
 
154
   NEW_LABEL(newlab, destobject);
 
155
   destobject->parts++;
 
156
   labeldefaults(*newlab, LOCAL, x, y);
 
157
 
 
158
   (*newlab)->string->type = TEXT_STRING; /* overwrites FONT record */
 
159
   (*newlab)->string->data.string = cstr;
 
160
   return *newlab;
 
161
}
 
162
 
 
163
/*--------------------------------------------------------------*/
 
164
/* Polygon constructor:  Create a new polygon element in the    */
 
165
/* object whose instance is "destinst" and return a pointer to  */
 
166
/* it.                                                          */
 
167
/*                                                              */
 
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.                                 */
 
175
/*                                                              */
 
176
/* Other properties must be set individually by the calling     */
 
177
/*      routine.                                                */
 
178
/*                                                              */
 
179
/* Return value is a pointer to the newly created polygon.      */
 
180
/*--------------------------------------------------------------*/
 
181
 
 
182
polyptr new_polygon(objinstptr destinst, pointlist *points, int number)
 
183
{
 
184
   polyptr *newpoly;
 
185
   objectptr destobject;
 
186
   objinstptr locdestinst;
 
187
 
 
188
   locdestinst = (destinst == NULL) ? areastruct.topinstance : destinst;
 
189
   destobject = locdestinst->thisobject;
 
190
 
 
191
   NEW_POLY(newpoly, destobject);
 
192
   destobject->parts++;
 
193
   polydefaults(*newpoly, 0, 0, 0);
 
194
   (*newpoly)->number = number;
 
195
   (*newpoly)->points = *points;
 
196
 
 
197
   calcbboxvalues(locdestinst, (genericptr *)newpoly);
 
198
   updatepagebounds(destobject);
 
199
   incr_changes(destobject);
 
200
   return *newpoly;
 
201
}
 
202
 
 
203
/*--------------------------------------------------------------*/
 
204
/* Spline constructor:  Create a new spline element in the      */
 
205
/* object whose instance is "destinst" and return a pointer to  */
 
206
/* it.                                                          */
 
207
/*                                                              */
 
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.   */
 
211
/*                                                              */
 
212
/* Other properties must be set individually by the calling     */
 
213
/*      routine.                                                */
 
214
/*                                                              */
 
215
/* Return value is a pointer to the newly created spline.       */
 
216
/*--------------------------------------------------------------*/
 
217
 
 
218
splineptr new_spline(objinstptr destinst, pointlist points)
 
219
{
 
220
   splineptr *newspline;
 
221
   objectptr destobject;
 
222
   objinstptr locdestinst;
 
223
   int i;
 
224
 
 
225
   locdestinst = (destinst == NULL) ? areastruct.topinstance : destinst;
 
226
   destobject = locdestinst->thisobject;
 
227
 
 
228
   NEW_SPLINE(newspline, destobject);
 
229
   destobject->parts++;
 
230
   splinedefaults(*newspline, 0, 0);
 
231
 
 
232
   for (i = 0; i < 4; i++)
 
233
      (*newspline)->ctrl[i] = points[i];
 
234
 
 
235
   calcspline(*newspline);
 
236
   calcbboxvalues(locdestinst, (genericptr *)newspline);
 
237
   updatepagebounds(destobject);
 
238
   incr_changes(destobject);
 
239
   return *newspline;
 
240
}
 
241
 
 
242
/*--------------------------------------------------------------*/
 
243
/* Arc constructor:  Create a new arc element in the object     */
 
244
/* whose instance is "destinst" and return a pointer to it.     */
 
245
/*                                                              */
 
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.         */
 
250
/*                                                              */
 
251
/* Other properties must be set individually by the calling     */
 
252
/*      routine.                                                */
 
253
/*                                                              */
 
254
/* Return value is a pointer to the newly created arc.          */
 
255
/*--------------------------------------------------------------*/
 
256
 
 
257
arcptr new_arc(objinstptr destinst, int radius, int x, int y)
 
258
{
 
259
   arcptr *newarc;
 
260
   objectptr destobject;
 
261
   objinstptr locdestinst;
 
262
 
 
263
   locdestinst = (destinst == NULL) ? areastruct.topinstance : destinst;
 
264
   destobject = locdestinst->thisobject;
 
265
 
 
266
   NEW_ARC(newarc, destobject);
 
267
   destobject->parts++;
 
268
   arcdefaults(*newarc, x, y);
 
269
   (*newarc)->radius = (*newarc)->yaxis = radius;
 
270
 
 
271
   calcarc(*newarc);
 
272
   calcbboxvalues(locdestinst, (genericptr *)newarc);
 
273
   updatepagebounds(destobject);
 
274
   incr_changes(destobject);
 
275
   return *newarc;
 
276
}
 
277
 
 
278
/*--------------------------------------------------------------*/
 
279
/* Instance constructor:  Create a new object instance element  */
 
280
/* in the object whose instance is "destinst" and return a      */
 
281
/* pointer to it.                                               */
 
282
/*                                                              */
 
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     */
 
286
/*         copy.                                                */
 
287
/*      "x" and "y" represents the instance position.           */
 
288
/*                                                              */
 
289
/* Other properties must be set individually by the calling     */
 
290
/*      routine.                                                */
 
291
/*                                                              */
 
292
/* Return value is a pointer to the newly created arc.          */
 
293
/*--------------------------------------------------------------*/
 
294
 
 
295
objinstptr new_objinst(objinstptr destinst, objinstptr srcinst, int x, int y)
 
296
{
 
297
   objinstptr *newobjinst;
 
298
   objectptr destobject;
 
299
   objinstptr locdestinst;
 
300
 
 
301
   locdestinst = (destinst == NULL) ? areastruct.topinstance : destinst;
 
302
   destobject = locdestinst->thisobject;
 
303
 
 
304
   NEW_OBJINST(newobjinst, destobject);
 
305
   destobject->parts++;
 
306
   instcopy(*newobjinst, srcinst);
 
307
   (*newobjinst)->position.x = x;
 
308
   (*newobjinst)->position.y = y;
 
309
 
 
310
   calcbboxvalues(locdestinst, (genericptr *)newobjinst);
 
311
   updatepagebounds(destobject);
 
312
   incr_changes(destobject);
 
313
   return *newobjinst;
 
314
}
 
315
 
 
316
/*--------------------------------------------------------------*/
 
317
/* Generic element destructor function                          */
 
318
/*--------------------------------------------------------------*/
 
319
 
 
320
void remove_element(objinstptr destinst, genericptr genelem)
 
321
{
 
322
   objectptr destobject;
 
323
   objinstptr locdestinst;
 
324
 
 
325
   locdestinst = (destinst == NULL) ? areastruct.topinstance : destinst;
 
326
   destobject = locdestinst->thisobject;
 
327
 
 
328
   genelem->type &= REMOVE_TAG;
 
329
   delete_tagged(destobject);
 
330
   calcbboxvalues(locdestinst, (genericptr *)NULL);
 
331
   updatepagebounds(destobject);
 
332
}
64
333
 
65
334
/*-------------------------------------*/
66
335
/* Sane values for a new path instance */
75
344
   newpath->parts = 0;
76
345
   newpath->plist = (genericptr *)NULL;
77
346
   newpath->passed = NULL;
78
 
   newpath->num_params = 0;
79
347
}
80
348
 
81
349
/*---------------------------------------*/
82
350
/* Sane values for a new object instance */
83
351
/*---------------------------------------*/
84
352
 
85
 
void objectdefaults(objinstptr newinst, objectptr thisobj, int x, int y)
 
353
void instancedefaults(objinstptr newinst, objectptr thisobj, int x, int y)
86
354
{
87
355
   newinst->position.x = x;
88
356
   newinst->position.y = y;
92
360
   newinst->color = areastruct.color;
93
361
   newinst->params = NULL;
94
362
   newinst->passed = NULL;
95
 
   newinst->num_params = 0;
96
363
 
97
364
   newinst->bbox.lowerleft.x = thisobj->bbox.lowerleft.x;
98
365
   newinst->bbox.lowerleft.y = thisobj->bbox.lowerleft.y;
99
366
   newinst->bbox.width = thisobj->bbox.width;
100
367
   newinst->bbox.height = thisobj->bbox.height;
101
368
 
102
 
#ifdef SCHEMA
103
369
   newinst->schembbox = NULL;
104
 
#endif
105
370
}
106
371
 
107
372
/*--------------------------------------*/
119
384
   if ((dotobj = finddot()) != (objectptr)NULL) {
120
385
      NEW_OBJINST(newdot, topobject);
121
386
      topobject->parts++;
122
 
      objectdefaults(*newdot, dotobj, xpos, ypos);
 
387
      instancedefaults(*newdot, dotobj, xpos, ypos);
 
388
      register_for_undo(XCF_Dot, UNDO_DONE, areastruct.topinstance, *newdot);
123
389
   }
124
390
   else {
125
391
      NEW_ARC(newarc, topobject);
129
395
      (*newarc)->yaxis = 6;
130
396
      (*newarc)->width = 1.0;
131
397
      (*newarc)->style = FILLED | FILLSOLID | NOBORDER;
132
 
      (*newarc)->num_params = 0;
133
398
      (*newarc)->passed = NULL;
134
399
      calcarc(*newarc);
 
400
      register_for_undo(XCF_Arc, UNDO_DONE, areastruct.topinstance, *newarc);
135
401
   }
136
402
   incr_changes(topobject);
137
403
}
138
404
 
139
 
/*----------------------*/
140
 
/* Start spline mode.   */
141
 
/*----------------------*/
142
 
 
143
 
void startspline(xcWidget button, caddr_t clientdata, caddr_t calldata)
144
 
{
145
 
   if (eventmode == NORMAL_MODE) {
146
 
      Wprintf("Click button1 and drag for spline.");
147
 
      eventmode = SPLINE0_MODE;
148
 
   }
149
 
}
150
 
 
151
 
/*----------------------*/
152
 
/* Start label mode.    */
153
 
/*----------------------*/
154
 
 
155
 
void starttext(xcWidget button, pointertype mode, caddr_t calldata)
156
 
{
157
 
   if (eventmode == NORMAL_MODE) {
158
 
      Wprintf("Click button1 for text.");
159
 
      texttype = (u_char)mode;
160
 
      eventmode = TEXT1_MODE;
161
 
   }
162
 
}
163
 
 
164
405
/*--------------------------------------*/
165
406
/* Sane default values for a label      */
166
407
/*--------------------------------------*/
171
412
   newlabel->color = areastruct.color;
172
413
   newlabel->scale = areastruct.textscale;
173
414
   newlabel->string = (stringpart *)malloc(sizeof(stringpart));
174
 
   newlabel->num_params = 0;
175
415
   newlabel->passed = NULL;
176
416
 
177
417
   /* initialize string with font designator */
179
419
   newlabel->string->data.font = areastruct.psfont;
180
420
   newlabel->string->nextpart = NULL;
181
421
 
182
 
#ifdef SCHEMA
183
422
   newlabel->pin = False;
184
423
   if (areastruct.schemon) {
185
424
      newlabel->pin = dopin;
186
425
      if (dopin == LOCAL) newlabel->color = LOCALPINCOLOR;
 
426
      else if (dopin == GLOBAL) newlabel->color = GLOBALPINCOLOR;
187
427
      else if (dopin == INFO) newlabel->color = INFOLABELCOLOR;
188
428
   }
189
 
#endif
190
429
 
191
430
   newlabel->justify = areastruct.justify;
192
431
   newlabel->position.x = x;
197
436
/* Button handler when creating a label */
198
437
/*--------------------------------------*/
199
438
 
200
 
void textbutton(u_char dopin, XButtonEvent *event)
 
439
void textbutton(u_char dopin, int x, int y)
201
440
{
202
441
   labelptr *newlabel;
203
442
   XPoint userpt;
211
450
 
212
451
   NEW_LABEL(newlabel, topobject);
213
452
   areastruct.editpart = topobject->parts;
214
 
   snap(event->x, event->y, &userpt);
 
453
   snap(x, y, &userpt);
215
454
   labeldefaults(*newlabel, dopin, userpt.x, userpt.y);
216
455
 
217
456
   tmpheight = (short)(TEXTHEIGHT * (*newlabel)->scale);
262
501
   labelptr tlab;
263
502
 
264
503
   for (tgen = topobject->plist; tgen < topobject->plist + topobject->parts; tgen++) {
265
 
      if ((*tgen)->type == LABEL) {
 
504
      if (IS_LABEL(*tgen)) {
266
505
         tlab = TOLABEL(tgen);
267
 
         if (tlab->pin == False) continue;
 
506
         if (tlab->pin != LOCAL) continue;
268
507
         else if (tlab == curlabel) continue;  /* Don't count self! */
269
508
         else if (!stringcomp(tlab->string, curstring)) return tlab;  
270
509
      }
276
515
/* Interpret string and add to current label.                   */
277
516
/*      keypressed is a KeySym                                  */
278
517
/*      clientdata can pass information for label controls      */
 
518
/*                                                              */
 
519
/* Return TRUE if labeltext handled the character, FALSE if the */
 
520
/* character was not recognized.                                */
279
521
/*--------------------------------------------------------------*/
280
522
 
281
 
void labeltext(int keypressed, char *clientdata)
 
523
Boolean labeltext(int keypressed, char *clientdata)
282
524
{
283
525
   labelptr curlabel;
284
 
   stringpart *curpos;
 
526
   stringpart *curpos, *labelbuf;
285
527
   int locpos;
286
 
   Boolean do_redraw = False;
 
528
   Boolean r, do_redraw = False;
287
529
   short tmplength, tmpheight, cfont;
288
530
   TextExtents tmpext;
289
531
 
291
533
 
292
534
   if (curlabel == NULL || textpos <= 0) {
293
535
      Wprintf("Error:  Bad label string");
294
 
      return;
 
536
      return FALSE;
295
537
   }
296
538
 
297
539
   /* find text segment of the current position */
299
541
 
300
542
   UDrawTLine(curlabel);
301
543
 
302
 
   if (isbound(keypressed, XCF_Text_Delete) && textpos > 1) {
303
 
      int curloc, strpos;
304
 
      stringpart *strptr;
305
 
 
306
 
      if (textend == 0) textend = textpos - 1;
307
 
 
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)) {
 
545
      if (textpos > 1) {
 
546
         int curloc, strpos;
 
547
         stringpart *strptr;
 
548
 
 
549
         if (textend == 0) textend = textpos - 1;
 
550
 
 
551
         undrawtext(curlabel);
 
552
         for (strpos = textpos - 1; strpos >= textend; strpos--) {
 
553
            strptr = findstringpart(strpos, &curloc, curlabel->string,
311
554
                         areastruct.topinstance);
312
 
         if (curloc >= 0) {
313
 
            memmove(strptr->data.string + curloc,
 
555
            if (curloc >= 0) {
 
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);
318
 
         }
319
 
 
320
 
         /* Don't delete any parameter boundaries---must use    */
321
 
         /* "unparameterize" command for that.                  */
322
 
 
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);
 
561
            }
 
562
 
 
563
            /* Don't delete any parameter boundaries---must use */
 
564
            /* "unparameterize" command for that.               */
 
565
 
 
566
            else if (strptr != NULL) {
 
567
               if ((strptr->type != PARAM_START) && (strptr->type != PARAM_END))
 
568
                  deletestring(strptr, &curlabel->string, areastruct.topinstance);
 
569
               else
 
570
                  textpos++;
 
571
            }
326
572
            else
327
 
               textpos++;
 
573
               Fprintf(stdout, "Error:  Unexpected NULL string part\n");
 
574
            textpos--;
 
575
         }
 
576
         textend = 0;
 
577
         do_redraw = True;
 
578
      }
 
579
   }
 
580
   else if (r = isbound(keypressed, XCF_Text_Delete_Param)) {
 
581
      if (textpos > 1) {
 
582
         int curloc, strpos;
 
583
         stringpart *strptr;
 
584
 
 
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);
 
593
            do_redraw = True;
328
594
         }
329
 
         else
330
 
            Fprintf(stdout, "Error:  Unexpected NULL string part\n");
331
 
         textpos--;
332
595
      }
333
 
      textend = 0;
334
 
      do_redraw = True;
335
596
   }
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;
340
600
 
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;
344
604
      }
345
 
      XDefineCursor(dpy, areastruct.areawin, CROSS);
 
605
      XDefineCursor(dpy, areastruct.areawin, DEFAULTCURSOR);
346
606
 
347
607
      Wprintf("");
348
608
 
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,
 
612
                    curlabel);
 
613
 
351
614
         incr_changes(topobject);
352
 
#ifdef SCHEMA
353
 
         topobject->valid = False;
354
 
#endif
355
 
 
356
 
      }
357
 
      else if (!hasstuff && (eventmode == TEXT3_MODE)) topobject->parts--;
 
615
         invalidate_netlist(topobject);
 
616
 
 
617
      }
 
618
      else if (!hasstuff && (eventmode == ETEXT_MODE)) {
 
619
         if (areastruct.editpart < topobject->parts) {
 
620
            short *sptr = allocselect();
 
621
            *sptr = areastruct.editpart;
 
622
 
 
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.                */
 
626
 
 
627
            xobjs.undostack->idx = -xobjs.undostack->idx;
 
628
            standard_element_delete(NORMAL);
 
629
         }
 
630
         else {
 
631
            /* Label had just been created; just delete it w/o undo */
 
632
            freelabel(curlabel->string);
 
633
            free(curlabel);
 
634
            topobject->parts--;
 
635
         }
 
636
      }
358
637
 
359
638
      if ((!hasstuff) && (eventmode == CATTEXT_MODE)) {  /* can't have null labels! */ 
360
 
          freelabel(curlabel->string);
361
 
          curlabel->string = stringcopyback(labelbuf, areastruct.topinstance);
362
 
          freelabel(labelbuf);
363
 
          labelbuf = NULL;
364
 
          resolveparams(areastruct.topinstance);
 
639
          undo_action();
365
640
          XcSetFunction(GXcopy);
366
641
          redrawtext(curlabel);
367
642
          Wprintf("Object must have a name!");
368
643
          eventmode = CATALOG_MODE;
369
644
      }
370
645
      else if (!hasstuff) {
371
 
          freelabel(curlabel->string);
372
 
          free(curlabel);
373
646
          eventmode = NORMAL_MODE;
374
647
      }
375
648
      else if (eventmode == CATTEXT_MODE) {
376
 
 
377
 
         /* set name of object to new string */
378
 
 
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);
 
649
         objectptr libobj;
 
650
         stringpart *oldname;
 
651
 
 
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) {
 
656
 
 
657
            /* set name of object to new string */
 
658
 
 
659
            strcpy(libobj->name, curlabel->string->nextpart->data.string);
 
660
 
386
661
            /* If checkname() alters the name, it has to be copied back to */
387
662
            /* the catalog label for the object.                           */
388
663
 
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);
398
672
            }
399
673
         }
400
674
         eventmode = CATALOG_MODE;
401
 
         objectdeselect();
 
675
         unselect_all();
402
676
      }
403
677
      else {    /* (hasstuff && eventmode != CATTEXT_MODE) */
404
678
         eventmode = NORMAL_MODE;
405
679
         incr_changes(topobject);
406
 
#ifdef SCHEMA
407
 
         if (curlabel->pin != False) topobject->valid = False;
408
 
#endif
 
680
         if (curlabel->pin != False) invalidate_netlist(topobject);
409
681
      }
410
682
 
411
683
      setdefaultfontmarks();
412
684
      setcolormark(areastruct.color);
413
 
      if (labelbuf != NULL) {
 
685
      if ((labelbuf = get_original_string(curlabel)) != NULL) {
414
686
 
415
 
#ifdef SCHEMA
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.                            */
420
691
 
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");
428
699
               else
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);
432
703
            }
433
704
         }
434
 
#endif
435
705
        
436
 
         freelabel(labelbuf);
437
 
         labelbuf = NULL;
438
706
         resolveparams(areastruct.topinstance);
439
 
         if (do_all >= 0)
440
 
            updateinstparam(areastruct.topinstance, do_all);
441
 
         else /* do_all == -1 */
442
 
            calcbbox(areastruct.topinstance);
443
 
#ifdef SCHEMA
 
707
         updateinstparam(topobject);
444
708
         setobjecttype(topobject);
445
 
#endif
446
709
      }
447
710
      else
448
711
         calcbbox(areastruct.topinstance);
449
 
      return;
450
 
   }
451
 
   else if (isbound(keypressed, XCF_Text_Right) && curpos != NULL)
452
 
      textpos++;
453
 
   else if (isbound(keypressed, XCF_Text_Left) && textpos > 1)
454
 
      textpos--;
455
 
   else if (isbound(keypressed, XCF_Text_Down)) {
 
712
 
 
713
      return r;
 
714
   }
 
715
   else if (r = isbound(keypressed, XCF_Text_Right)) {
 
716
      if (curpos != NULL) textpos++;
 
717
   }
 
718
   else if (r = isbound(keypressed, XCF_Text_Left)) {
 
719
      if (textpos > 1) textpos--;
 
720
   }
 
721
   else if (r = isbound(keypressed, XCF_Text_Down)) {
456
722
      while (curpos != NULL) {
457
723
         textpos++;
458
724
         curpos = findstringpart(textpos, &locpos, curlabel->string,
462
728
               break;
463
729
      }
464
730
   }
465
 
   else if (isbound(keypressed, XCF_Text_Up)) {
 
731
   else if (r = isbound(keypressed, XCF_Text_Up)) {
466
732
      while (textpos > 1) {
467
733
         textpos--;
468
734
         curpos = findstringpart(textpos, &locpos, curlabel->string,
473
739
         }
474
740
      }
475
741
   }
476
 
   else if (isbound(keypressed, XCF_Text_Home))
 
742
   else if (r = isbound(keypressed, XCF_Text_Home))
477
743
      textpos = 1;
478
 
   else if (isbound(keypressed, XCF_Text_End))
 
744
   else if (r = isbound(keypressed, XCF_Text_End))
479
745
      textpos = stringlength(curlabel->string, True, areastruct.topinstance);
480
 
   else if (isbound(keypressed, XCF_Text_Split)) {
 
746
   else if (r = isbound(keypressed, XCF_Text_Split)) {
481
747
      labelptr *newlabel;
482
748
      XPoint points[4], points1[4], points2[4];
483
749
 
523
789
   /* Write a font designator or other control into the string */
524
790
 
525
791
   if (clientdata != NULL) {
 
792
      oparamptr ops;
526
793
      stringpart *newpart;
527
794
      Boolean errcond = False;
528
795
 
551
818
            if (newpart->data.font >= fontcount) errcond = True;
552
819
            break;
553
820
         case PARAM_START:
554
 
            newpart->data.paramno = *((int *)clientdata);
555
 
            if (newpart->data.paramno >= topobject->num_params) errcond = True;
556
 
            else if (topobject->params[newpart->data.paramno]->type != XC_STRING)
557
 
               errcond = True;
 
821
            newpart->data.string = (char *)malloc(1 + strlen(clientdata));
 
822
            strcpy(newpart->data.string, clientdata);
 
823
            ops = match_param(topobject, clientdata);
 
824
            if (ops == NULL) errcond = True;
558
825
            break;
559
826
      }
560
827
      if (errcond == True) {
561
828
         Wprintf("Error in insertion.  Ignoring.");
562
829
         deletestring(newpart, &curlabel->string, areastruct.topinstance);
563
830
      }
564
 
      else
 
831
      else {
565
832
         textpos++;
 
833
         r = TRUE;
 
834
      }
566
835
      do_redraw = True;
567
836
   }
568
837
 
579
848
      if (locpos < 0) {
580
849
 
581
850
         /* Find part of string which is immediately in front of textpos */
582
 
         lastpos = findstringpart(textpos - 1, &locpos, curlabel->string, areastruct.topinstance);
 
851
         lastpos = findstringpart(textpos - 1, &locpos, curlabel->string,
 
852
                areastruct.topinstance);
583
853
 
584
854
         /* No text on either side to attach to: make a new text segment */
585
855
         if (locpos < 0) {
606
876
      }
607
877
      textpos++;        /* move forward to next text position */
608
878
      do_redraw = True;
 
879
      r = TRUE;
609
880
   }
610
881
 
611
882
   /* Redraw the label */
613
884
   if (do_redraw) {
614
885
      short beglength;
615
886
 
616
 
      tmpext = ULength(curlabel->string, areastruct.topinstance, curlabel->scale, textpos, NULL);
 
887
      tmpext = ULength(curlabel->string, areastruct.topinstance, curlabel->scale,
 
888
                textpos, NULL);
617
889
      beglength = tmpext.width;
618
890
        
619
 
      tmpext = ULength(curlabel->string, areastruct.topinstance, curlabel->scale, 0, NULL);
 
891
      tmpext = ULength(curlabel->string, areastruct.topinstance, curlabel->scale,
 
892
                0, NULL);
620
893
      tmplength = tmpext.width;
621
894
      tmpheight = (short)(curlabel->scale * TEXTHEIGHT);
622
895
      areastruct.origin.x = curlabel->position.x + (curlabel->justify & NOTLEFT
625
898
      areastruct.origin.y = curlabel->position.y + (curlabel->justify &
626
899
          NOTBOTTOM ? (curlabel->justify & TOP ? -tmpheight : -tmpheight / 2)
627
900
          : 0);
628
 
#ifdef SCHEMA
629
901
      if (curlabel->pin)
630
902
         pinadjust(curlabel->justify, &(areastruct.origin.x),
631
903
                &(areastruct.origin.y), 1);
632
 
#endif
633
904
      XcSetFunction(GXcopy);
634
905
      redrawtext(curlabel);
635
906
   }
 
907
 
636
908
   UDrawTLine(curlabel);
637
909
 
638
 
   /* Report on characters at the cursor position in the message window */
639
 
 
640
 
   charreport(curlabel);
641
 
 
642
 
   /* find current font and adjust menubuttons as necessary */
643
 
 
644
 
   cfont = findcurfont(textpos, curlabel->string, areastruct.topinstance);
645
 
   if (cfont < 0) {
646
 
      Wprintf("Error:  Illegal label string");
647
 
      return;
 
910
   if (r || do_redraw) {
 
911
 
 
912
      /* Report on characters at the cursor position in the message window */
 
913
 
 
914
      charreport(curlabel);
 
915
 
 
916
      /* find current font and adjust menubuttons as necessary */
 
917
 
 
918
      cfont = findcurfont(textpos, curlabel->string, areastruct.topinstance);
 
919
      if (cfont < 0) {
 
920
         Wprintf("Error:  Illegal label string");
 
921
         return r;
 
922
      }
 
923
      else
 
924
         setfontmarks(cfont, -1);
 
925
 
 
926
      textend = 0;
648
927
   }
649
 
   else
650
 
      setfontmarks(cfont, -1);
651
 
 
652
 
   textend = 0;
 
928
   return r;
653
929
}
654
930
 
655
931
/*-------------------------------------*/
676
952
   Boolean changed = False;
677
953
   static short transjust[] = {15, 13, 12, 7, 5, 4, 3, 1, 0};
678
954
 
679
 
   if (eventmode == TEXT2_MODE || eventmode == TEXT3_MODE) {
 
955
   if (eventmode == TEXT_MODE || eventmode == ETEXT_MODE) {
680
956
      curlabel = TOLABEL(EDITPART);
681
957
      UDrawTLine(curlabel);
682
958
      undrawtext(curlabel);
683
959
      jsave = curlabel->justify;
684
960
      curlabel->justify = transjust[mode] |
685
 
                (curlabel->justify & (FLIPINV | PINVISIBLE));
 
961
                (curlabel->justify & NONJUSTFIELD);
686
962
      if (jsave != curlabel->justify) changed = True;
687
963
      redrawtext(curlabel);
688
964
      UDrawTLine(curlabel);
697
973
            jsave = curlabel->justify;
698
974
            undrawtext(curlabel);
699
975
            curlabel->justify = transjust[mode] |
700
 
                (curlabel->justify & (FLIPINV | PINVISIBLE));
 
976
                (curlabel->justify & NONJUSTFIELD);
701
977
            if (jsave != curlabel->justify) changed = True;
702
 
            redrawtext(curlabel);
703
978
         }
704
979
      }
705
 
      if (eventmode != PRESS_MODE && eventmode != COPY2_MODE) objectdeselect();
 
980
      if (eventmode != MOVE_MODE && eventmode != COPY_MODE)
 
981
         unselect_all();
 
982
      else
 
983
         draw_all_selected();
706
984
   }
707
985
   if (curlabel == NULL)
708
986
      Wprintf("No labels chosen to rejustify");
709
987
   else if (changed) {
710
988
      pwriteback(areastruct.topinstance);
 
989
      calcbbox(areastruct.topinstance);
711
990
      incr_changes(topobject);
712
 
 
713
991
   }
714
992
}
715
993
 
730
1008
   newspline->width = areastruct.linewidth;
731
1009
   newspline->style = areastruct.style;
732
1010
   newspline->color = areastruct.color;
733
 
   newspline->num_params = 0;
734
1011
   newspline->passed = NULL;
735
1012
   calcspline(newspline);
736
1013
}
739
1016
/* Start drawing a spline. */
740
1017
/*-------------------------*/
741
1018
 
742
 
void splinebutton(XButtonEvent *event)
 
1019
void splinebutton(int x, int y)
743
1020
{
744
1021
   splineptr *newspline;
745
1022
   XPoint userpt;
747
1024
   NEW_SPLINE(newspline, topobject);
748
1025
   areastruct.editpart = topobject->parts;
749
1026
 
750
 
   snap(event->x, event->y, &userpt);
 
1027
   snap(x, y, &userpt);
751
1028
   areastruct.editcycle = 3;
752
1029
   splinedefaults(*newspline, userpt.x, userpt.y);
753
1030
 
793
1070
   printpos(newpos.x, newpos.y);
794
1071
   areastruct.save.x = newpos.x;
795
1072
   areastruct.save.y = newpos.y;
796
 
}
797
 
 
798
 
/*--------------------------*/
799
 
/* Start drawing a polygon. */
800
 
/*--------------------------*/
801
 
 
802
 
void startpoly(xcWidget button, caddr_t clientdata, caddr_t calldata)
803
 
{
804
 
   if (eventmode == NORMAL_MODE) {
805
 
      Wprintf("Click button1 to start the polygon.");
806
 
      eventmode = POLY_MODE;
807
 
   }
808
 
}
809
 
 
810
 
/*-----------------------*/
811
 
/* Start drawing an arc. */
812
 
/*-----------------------*/
813
 
 
814
 
void startarc(xcWidget button, caddr_t clientdata, caddr_t calldata)
815
 
{
816
 
   if (eventmode == NORMAL_MODE) {
817
 
      Wprintf("Click button1 and drag to make arc.");
818
 
      eventmode = ARC0_MODE;
819
 
   }
 
1073
 
 
1074
   flusharea();
820
1075
}
821
1076
 
822
1077
/*--------------------------------------*/
834
1089
   newarc->yaxis = 0;
835
1090
   newarc->angle1 = 0;
836
1091
   newarc->angle2 = 360;
837
 
   newarc->num_params = 0;
838
1092
   newarc->passed = NULL;
839
1093
   calcarc(newarc);
840
1094
}
843
1097
/* Button handler when creating an arc */
844
1098
/*-------------------------------------*/
845
1099
 
846
 
void arcbutton(XButtonEvent *event)
 
1100
void arcbutton(int x, int y)
847
1101
{
848
1102
   arcptr *newarc;
849
1103
   XPoint userpt;
850
1104
 
851
1105
   NEW_ARC(newarc, topobject);
852
1106
   areastruct.editpart = topobject->parts;
853
 
   snap(event->x, event->y, &userpt);
 
1107
   snap(x, y, &userpt);
854
1108
   areastruct.editcycle = 0;
855
1109
   saveratio = 1.0;
856
1110
   arcdefaults(*newarc, userpt.x, userpt.y);
931
1185
 
932
1186
   areastruct.save.x = newpos.x;
933
1187
   areastruct.save.y = newpos.y;
934
 
}
935
 
 
936
 
/*----------------------*/
937
 
/* Start drawing a box. */
938
 
/*----------------------*/
939
 
 
940
 
void startbox(xcWidget button, caddr_t clientdata, caddr_t calldata)
941
 
{
942
 
   if (eventmode == NORMAL_MODE) {
943
 
      Wprintf("Click button1 and drag to make box.");
944
 
      eventmode = BOX0_MODE;
945
 
   }
 
1188
 
 
1189
   flusharea();
946
1190
}
947
1191
 
948
1192
/*--------------------------------------*/
957
1201
   newpoly->color = areastruct.color;
958
1202
   newpoly->width = areastruct.linewidth;
959
1203
   newpoly->number = number;
960
 
   newpoly->points = (pointlist) malloc(number * sizeof(XPoint));
961
 
   newpoly->num_params = 0;
962
1204
   newpoly->passed = NULL;
963
 
   for (pointptr = newpoly->points; pointptr < newpoly->points + number;
964
 
        pointptr++) {
965
 
      pointptr->x = x;
966
 
      pointptr->y = y;
 
1205
   if (number == 0)
 
1206
      newpoly->points = NULL;
 
1207
   else {
 
1208
      newpoly->points = (pointlist) malloc(number * sizeof(XPoint));
 
1209
 
 
1210
      for (pointptr = newpoly->points; pointptr < newpoly->points + number;
 
1211
                pointptr++) {
 
1212
         pointptr->x = x;
 
1213
         pointptr->y = y;
 
1214
      }
967
1215
   }
968
1216
}
969
1217
 
971
1219
/* Button handler when creating a box */
972
1220
/*------------------------------------*/
973
1221
 
974
 
void boxbutton(XButtonEvent *event)
 
1222
void boxbutton(int x, int y)
975
1223
{
976
1224
   polyptr *newbox;
977
1225
   XPoint userpt;
978
1226
 
979
1227
   NEW_POLY(newbox, topobject);
980
1228
   areastruct.editpart = topobject->parts;
981
 
   snap(event->x, event->y, &userpt);
 
1229
   snap(x, y, &userpt);
982
1230
   polydefaults(*newbox, 4, userpt.x, userpt.y);
983
1231
 
984
1232
   XcSetXORFg(areastruct.color, BACKGROUND);
1018
1266
 
1019
1267
   areastruct.save.x = newpos.x;
1020
1268
   areastruct.save.y = newpos.y;
 
1269
 
 
1270
   flusharea();
1021
1271
}
1022
1272
 
1023
1273
/*----------------------------------*/
1044
1294
      areastruct.save.y = newpos.y;
1045
1295
      printpos(newpos.x, newpos.y);
1046
1296
   }
 
1297
 
 
1298
   flusharea();
1047
1299
}
1048
1300
 
1049
1301
/*--------------------------*/
1065
1317
   (*newwire)->number = 2;
1066
1318
   (*newwire)->width = areastruct.linewidth;
1067
1319
   (*newwire)->points = (pointlist) malloc(2 * sizeof(XPoint));
1068
 
   (*newwire)->num_params = 0;
1069
1320
   (*newwire)->passed = NULL;
1070
1321
   pointptr = (*newwire)->points;
1071
1322
   pointptr->x = (pointptr + 1)->x = areastruct.save.x = userpt.x;
1219
1470
   printpos(newpos.x, newpos.y);
1220
1471
   areastruct.save.x = newpos.x;
1221
1472
   areastruct.save.y = newpos.y;
 
1473
 
 
1474
   flusharea();
1222
1475
}
1223
1476
 
1224
1477
/*-------------------------------------------------*/
1229
1482
{
1230
1483
   genericptr *sptr = topobject->plist + (*scnt);
1231
1484
 
1232
 
   switch((*sptr)->type) {
 
1485
   switch(ELEMENTTYPE(*sptr)) {
1233
1486
      case POLYGON:
1234
1487
         if (direc)
1235
1488
            *endpoint = TOPOLY(sptr)->points + TOPOLY(sptr)->number - 1;
1303
1556
/*      add = 1 if plist has (parts + 1) elements               */
1304
1557
/*--------------------------------------------------------------*/
1305
1558
 
1306
 
void freeparts(short *selectobj, short add)
 
1559
void freepathparts(short *selectobj, short add)
1307
1560
{
1308
1561
   genericptr *oldelem = topobject->plist + (*selectobj);
1309
 
   switch((*oldelem)->type) {
 
1562
   switch(ELEMENTTYPE(*oldelem)) {
1310
1563
      case POLYGON:
1311
1564
         free((TOPOLY(oldelem))->points);
1312
1565
         break;
1313
 
      case PATH:
1314
 
         free((TOPATH(oldelem))->plist);
1315
 
         break;
1316
 
      case LABEL:
1317
 
         free((TOLABEL(oldelem))->string);
1318
 
         break;
1319
1566
   }
1320
1567
   free(*oldelem);
1321
1568
   removep(selectobj, add);
1346
1593
   genericptr *genp, *newg;
1347
1594
   pathptr oldpath;
1348
1595
 
1349
 
   if (areastruct.selects == 0) objectselect(PATH);
 
1596
   if (areastruct.selects == 0) select_element(PATH);
1350
1597
   if (areastruct.selects == 0) {
1351
1598
      Wprintf("No objects selected.");
1352
1599
      return;
1379
1626
 
1380
1627
         /* remove the path object and revise the selectlist */
1381
1628
 
1382
 
         freeparts(selectobj, 0);
1383
 
         reviseselect(selectobj);
 
1629
         freepathparts(selectobj, 0);
 
1630
         reviseselect(areastruct.selectlist, areastruct.selects, selectobj);
1384
1631
      }
1385
1632
   }
1386
1633
   clearselects();
1574
1821
      (*newpoly)->width  = polywidth;
1575
1822
      (*newpoly)->style  = polytype;
1576
1823
      (*newpoly)->color  = polycolor;
1577
 
      (*newpoly)->num_params = 0;
1578
1824
      (*newpoly)->passed = NULL;
1579
1825
 
1580
1826
      /* insert the points into the new polygon */
1607
1853
 
1608
1854
      for (sptr = scount; sptr < scount + numpolys; sptr++) {
1609
1855
         easydraw(*sptr, DOFORALL);
1610
 
         freeparts(sptr, 1);
 
1856
         freepathparts(sptr, 1);
1611
1857
         /* revise the list of path elements */
1612
1858
         for (sptr2 = sptr + 1; sptr2 < scount + numpolys; sptr2++)
1613
1859
            if (*sptr2 > *sptr) (*sptr2)--;
1624
1870
      (*newpath)->width = polywidth;
1625
1871
      (*newpath)->parts = numpolys;
1626
1872
      (*newpath)->plist = (genericptr *) malloc(numpolys * sizeof(genericptr));
1627
 
      (*newpath)->num_params = 0;
1628
1873
      (*newpath)->passed = NULL;
1629
1874
 
1630
1875
      /* move the elements from the top level into the path structure */
1637
1882
         /* reverse point order if necessary */
1638
1883
 
1639
1884
         if (*(direc + (short)(sptr - order)) == 1) {
1640
 
            switch ((*newelem)->type) {
 
1885
            switch (ELEMENTTYPE(*newelem)) {
1641
1886
               case POLYGON:
1642
1887
                  reversepoints(TOPOLY(newelem)->points, TOPOLY(newelem)->number);
1643
1888
                  break;
1674
1919
   free(direc);
1675
1920
}
1676
1921
 
 
1922
/*----------------------------------------------*/
 
1923
/* Add a new point to a polygon                 */
 
1924
/*----------------------------------------------*/
 
1925
 
 
1926
void poly_add_point(polyptr thispoly, XPoint *newpoint) {
 
1927
   XPoint *tpoint;
 
1928
 
 
1929
   thispoly->number++;
 
1930
   thispoly->points = (XPoint *)realloc(thispoly->points,
 
1931
                        thispoly->number * sizeof(XPoint));
 
1932
   tpoint = thispoly->points + thispoly->number - 1;
 
1933
   tpoint->x = newpoint->x;
 
1934
   tpoint->y = newpoint->y;
 
1935
}
 
1936
 
1677
1937
/*-------------------------------------------------*/
1678
1938
/* ButtonPress handler while a wire is being drawn */
1679
1939
/*-------------------------------------------------*/
1680
1940
 
1681
 
void wirebutton(XButtonEvent *event)
 
1941
void wire_op(int op, int x, int y)
1682
1942
{
1683
1943
   XPoint userpt, *tpoint;
1684
1944
   polyptr newwire;
1685
1945
 
1686
 
   snap(event->x, event->y, &userpt);
 
1946
   snap(x, y, &userpt);
1687
1947
 
1688
1948
   newwire = TOPOLY(EDITPART);
1689
1949
   if (areastruct.manhatn) manhattanize(&userpt, newwire);
1696
1956
   tpoint->x = userpt.x;
1697
1957
   tpoint->y = userpt.y;
1698
1958
 
 
1959
   /* cancel wire operation completely */
 
1960
   if (op == XCF_Cancel) {
 
1961
      free(newwire->points);
 
1962
      free(newwire);
 
1963
      newwire = NULL;
 
1964
      eventmode = NORMAL_MODE;
 
1965
   }
 
1966
 
1699
1967
   /* back up one point; prevent length zero wires */
1700
 
   if ((event->button == Button3) || ((tpoint - 1)->x == userpt.x &&
 
1968
   else if ((op == XCF_Cancel_Last) || ((tpoint - 1)->x == userpt.x &&
1701
1969
           (tpoint - 1)->y == userpt.y)) {
1702
1970
      if (newwire->number <= 2) {
1703
1971
         free(newwire->points);
1711
1979
      }
1712
1980
   }
1713
1981
 
1714
 
   if (newwire && event->button == Button1) {
1715
 
      if (++newwire->number == 3) newwire->style = areastruct.style;
1716
 
      newwire->points = (XPoint *)realloc(newwire->points, newwire->number
1717
 
                * sizeof(XPoint));
1718
 
      tpoint = newwire->points + newwire->number - 1;
1719
 
      tpoint->x = userpt.x;
1720
 
      tpoint->y = userpt.y;
 
1982
   if (newwire && (op == XCF_Wire || op == XCF_Continue_Element)) {
 
1983
      if (newwire->number == 2)
 
1984
         newwire->style = areastruct.style;
 
1985
      poly_add_point(newwire, &userpt);
1721
1986
   }
1722
 
   else if (newwire == NULL || event->button != Button3)
 
1987
   else if ((newwire == NULL) || op == XCF_Finish_Element || op == XCF_Cancel)
1723
1988
      xcRemoveEventHandler(areastruct.area, PointerMotionMask, False,
1724
1989
         (xcEventHandler)trackwire, NULL);
1725
1990
 
1726
1991
   if (newwire) {
1727
 
      if (event->button == Button2) {
 
1992
      if (op == XCF_Finish_Element) {
1728
1993
         XcSetFunction(GXcopy);
1729
1994
         XcSetForeground(newwire->color);
1730
1995
         topobject->parts++;
1731
1996
         incr_changes(topobject);
1732
 
#ifdef SCHEMA
1733
 
         if (!nonnetwork(newwire)) topobject->valid = False;
1734
 
#endif
 
1997
         if (!nonnetwork(newwire)) invalidate_netlist(topobject);
 
1998
         register_for_undo(XCF_Wire, UNDO_DONE, areastruct.topinstance, newwire);
1735
1999
      }
1736
2000
      UDrawPolygon(newwire);
1737
 
      if (event->button == Button3)
 
2001
      if (op == XCF_Cancel_Last)
1738
2002
         checkwarp(newwire->points + newwire->number - 1);
1739
2003
   }
 
2004
 
 
2005
   if (op == XCF_Finish_Element) {
 
2006
      eventmode = NORMAL_MODE;
 
2007
      singlebbox(EDITPART);
 
2008
   }
1740
2009
}
1741
2010
 
1742
2011
/*-------------------------------------------------------------------------*/