2 /* 15 Oct 2008 Ineiev: add different crosshair shapes */
7 * PCB, interactive printed circuit board design
8 * Copyright (C) 1994,1995,1996 Thomas Nau
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 * Contact addresses for paper mail and Email:
25 * Thomas Nau, Schlehenweg 15, 88471 Baustetten, Germany
26 * Thomas.Nau@rz.uni-ulm.de
43 #include "crosshair.h"
52 #ifdef HAVE_LIBDMALLOC
59 #define ABS(x) (((x)<0)?-(x):(x))
67 /* ---------------------------------------------------------------------------
68 * some local identifiers
71 /* This is a stack for HideCrosshair() and RestoreCrosshair() calls. They
72 * must always be matched. */
73 static Boolean CrosshairStack
[MAX_CROSSHAIRSTACK_DEPTH
];
74 static int CrosshairStackLocation
= 0;
76 /* ---------------------------------------------------------------------------
77 * some local prototypes
79 static void XORPolygon (PolygonTypePtr
, LocationType
, LocationType
);
80 static void XORDrawElement (ElementTypePtr
, LocationType
, LocationType
);
81 static void XORDrawBuffer (BufferTypePtr
);
82 static void XORDrawInsertPointObject (void);
83 static void XORDrawMoveOrCopyObject (void);
84 static void XORDrawAttachedLine (LocationType
, LocationType
, LocationType
,
85 LocationType
, BDimension
);
86 static void XORDrawAttachedArc (BDimension
);
87 static void DrawAttached (Boolean
);
89 /* ---------------------------------------------------------------------------
90 * creates a tmp polygon with coordinates converted to screen system
93 XORPolygon (PolygonTypePtr polygon
, LocationType dx
, LocationType dy
)
96 for (i
= 0; i
< polygon
->PointN
- 1; i
++)
97 gui
->draw_line (Crosshair
.GC
,
98 polygon
->Points
[i
].X
+ dx
, polygon
->Points
[i
].Y
+ dy
,
99 polygon
->Points
[i
+ 1].X
+ dx
,
100 polygon
->Points
[i
+ 1].Y
+ dy
);
102 gui
->draw_line (Crosshair
.GC
,
103 polygon
->Points
[i
].X
+ dx
, polygon
->Points
[i
].Y
+ dy
,
104 polygon
->Points
[0].X
+ dx
, polygon
->Points
[0].Y
+ dy
);
107 /*-----------------------------------------------------------
108 * Draws the outline of an arc
111 XORDrawAttachedArc (BDimension thick
)
117 BDimension wid
= thick
/ 2;
119 wx
= Crosshair
.X
- Crosshair
.AttachedBox
.Point1
.X
;
120 wy
= Crosshair
.Y
- Crosshair
.AttachedBox
.Point1
.Y
;
121 if (wx
== 0 && wy
== 0)
123 arc
.X
= Crosshair
.AttachedBox
.Point1
.X
;
124 arc
.Y
= Crosshair
.AttachedBox
.Point1
.Y
;
125 if (XOR (Crosshair
.AttachedBox
.otherway
, abs (wy
) > abs (wx
)))
127 arc
.X
= Crosshair
.AttachedBox
.Point1
.X
+ abs (wy
) * SGNZ (wx
);
128 sa
= (wx
>= 0) ? 0 : 180;
130 if (abs (wy
) >= 2 * abs (wx
))
131 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? 45 : -45;
134 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? 90 : -90;
138 arc
.Y
= Crosshair
.AttachedBox
.Point1
.Y
+ abs (wx
) * SGNZ (wy
);
139 sa
= (wy
>= 0) ? -90 : 90;
141 if (abs (wx
) >= 2 * abs (wy
))
142 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? -45 : 45;
145 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? -90 : 90;
151 arc
.Width
= arc
.Height
= wy
;
152 bx
= GetArcEnds (&arc
);
154 gui
->draw_arc (Crosshair
.GC
, arc
.X
, arc
.Y
, wy
+ wid
, wy
+ wid
, sa
, dir
);
155 if (wid
> pixel_slop
)
157 gui
->draw_arc (Crosshair
.GC
, arc
.X
, arc
.Y
, wy
- wid
, wy
- wid
, sa
, dir
);
158 gui
->draw_arc (Crosshair
.GC
, bx
->X1
, bx
->Y1
,
159 wid
, wid
, sa
, -180 * SGN (dir
));
160 gui
->draw_arc (Crosshair
.GC
, bx
->X2
, bx
->Y2
,
161 wid
, wid
, sa
+ dir
, 180 * SGN (dir
));
165 /*-----------------------------------------------------------
166 * Draws the outline of a line
169 XORDrawAttachedLine (LocationType x1
, LocationType y1
, LocationType x2
,
170 LocationType y2
, BDimension thick
)
172 LocationType dx
, dy
, ox
, oy
;
177 if (dx
!= 0 || dy
!= 0)
178 h
= 0.5 * thick
/ sqrt (SQUARE (dx
) + SQUARE (dy
));
181 ox
= dy
* h
+ 0.5 * SGN (dy
);
182 oy
= -(dx
* h
+ 0.5 * SGN (dx
));
183 gui
->draw_line (Crosshair
.GC
, x1
+ ox
, y1
+ oy
, x2
+ ox
, y2
+ oy
);
184 if (abs (ox
) >= pixel_slop
|| abs (oy
) >= pixel_slop
)
186 LocationType angle
= atan2 ((float) dx
, (float) dy
) * 57.295779;
187 gui
->draw_line (Crosshair
.GC
, x1
- ox
, y1
- oy
, x2
- ox
, y2
- oy
);
188 gui
->draw_arc (Crosshair
.GC
,
189 x1
, y1
, thick
/ 2, thick
/ 2, angle
- 180, 180);
190 gui
->draw_arc (Crosshair
.GC
, x2
, y2
, thick
/ 2, thick
/ 2, angle
, 180);
194 /* ---------------------------------------------------------------------------
195 * draws the elements of a loaded circuit which is to be merged in
198 XORDrawElement (ElementTypePtr Element
, LocationType DX
, LocationType DY
)
200 /* if no silkscreen, draw the bounding box */
201 if (Element
->ArcN
== 0 && Element
->LineN
== 0)
203 gui
->draw_line (Crosshair
.GC
,
204 DX
+ Element
->BoundingBox
.X1
,
205 DY
+ Element
->BoundingBox
.Y1
,
206 DX
+ Element
->BoundingBox
.X1
,
207 DY
+ Element
->BoundingBox
.Y2
);
208 gui
->draw_line (Crosshair
.GC
,
209 DX
+ Element
->BoundingBox
.X1
,
210 DY
+ Element
->BoundingBox
.Y2
,
211 DX
+ Element
->BoundingBox
.X2
,
212 DY
+ Element
->BoundingBox
.Y2
);
213 gui
->draw_line (Crosshair
.GC
,
214 DX
+ Element
->BoundingBox
.X2
,
215 DY
+ Element
->BoundingBox
.Y2
,
216 DX
+ Element
->BoundingBox
.X2
,
217 DY
+ Element
->BoundingBox
.Y1
);
218 gui
->draw_line (Crosshair
.GC
,
219 DX
+ Element
->BoundingBox
.X2
,
220 DY
+ Element
->BoundingBox
.Y1
,
221 DX
+ Element
->BoundingBox
.X1
,
222 DY
+ Element
->BoundingBox
.Y1
);
226 ELEMENTLINE_LOOP (Element
);
228 gui
->draw_line (Crosshair
.GC
,
231 DX
+ line
->Point2
.X
, DY
+ line
->Point2
.Y
);
235 /* arc coordinates and angles have to be converted to X11 notation */
238 gui
->draw_arc (Crosshair
.GC
,
241 arc
->Width
, arc
->Height
, arc
->StartAngle
, arc
->Delta
);
245 /* pin coordinates and angles have to be converted to X11 notation */
248 gui
->draw_arc (Crosshair
.GC
,
251 pin
->Thickness
/ 2, pin
->Thickness
/ 2, 0, 360);
258 if ((TEST_FLAG (ONSOLDERFLAG
, pad
) != 0) ==
259 Settings
.ShowSolderSide
|| PCB
->InvisibleObjectsOn
)
261 if (pad
->Point1
.X
== pad
->Point2
.X
262 || pad
->Point1
.Y
== pad
->Point2
.Y
)
264 int minx
, miny
, maxx
, maxy
;
265 minx
= DX
+ MIN (pad
->Point1
.X
, pad
->Point2
.X
) - pad
->Thickness
/2;
266 maxx
= DX
+ MAX (pad
->Point1
.X
, pad
->Point2
.X
) + pad
->Thickness
/2;
267 miny
= DY
+ MIN (pad
->Point1
.Y
, pad
->Point2
.Y
) - pad
->Thickness
/2;
268 maxy
= DY
+ MAX (pad
->Point1
.Y
, pad
->Point2
.Y
) + pad
->Thickness
/2;
269 gui
->draw_line (Crosshair
.GC
, minx
, miny
, maxx
, miny
);
270 gui
->draw_line (Crosshair
.GC
, minx
, miny
, minx
, maxy
);
271 gui
->draw_line (Crosshair
.GC
, maxx
, miny
, maxx
, maxy
);
272 gui
->draw_line (Crosshair
.GC
, minx
, maxy
, maxx
, maxy
);
276 /* FIXME: draw outlines, not centerlines. */
277 gui
->draw_line (Crosshair
.GC
,
278 DX
+ pad
->Point1
.X
, DY
+ pad
->Point1
.Y
,
279 DX
+ pad
->Point2
.X
, DY
+ pad
->Point2
.Y
);
285 gui
->draw_line (Crosshair
.GC
,
286 Element
->MarkX
+ DX
- EMARK_SIZE
,
288 Element
->MarkX
+ DX
, Element
->MarkY
+ DY
- EMARK_SIZE
);
289 gui
->draw_line (Crosshair
.GC
,
290 Element
->MarkX
+ DX
+ EMARK_SIZE
,
292 Element
->MarkX
+ DX
, Element
->MarkY
+ DY
- EMARK_SIZE
);
293 gui
->draw_line (Crosshair
.GC
,
294 Element
->MarkX
+ DX
- EMARK_SIZE
,
296 Element
->MarkX
+ DX
, Element
->MarkY
+ DY
+ EMARK_SIZE
);
297 gui
->draw_line (Crosshair
.GC
,
298 Element
->MarkX
+ DX
+ EMARK_SIZE
,
300 Element
->MarkX
+ DX
, Element
->MarkY
+ DY
+ EMARK_SIZE
);
303 /* ---------------------------------------------------------------------------
304 * draws all visible and attached objects of the pastebuffer
307 XORDrawBuffer (BufferTypePtr Buffer
)
313 x
= Crosshair
.X
- Buffer
->X
;
314 y
= Crosshair
.Y
- Buffer
->Y
;
316 /* draw all visible layers */
317 for (i
= 0; i
< max_layer
+ 2; i
++)
318 if (PCB
->Data
->Layer
[i
].On
)
320 LayerTypePtr layer
= &Buffer
->Data
->Layer
[i
];
325 XORDrawAttachedLine(x +line->Point1.X,
326 y +line->Point1.Y, x +line->Point2.X,
327 y +line->Point2.Y, line->Thickness);
329 gui
->draw_line (Crosshair
.GC
,
330 x
+ line
->Point1
.X
, y
+ line
->Point1
.Y
,
331 x
+ line
->Point2
.X
, y
+ line
->Point2
.Y
);
336 gui
->draw_arc (Crosshair
.GC
,
340 arc
->Height
, arc
->StartAngle
, arc
->Delta
);
345 BoxTypePtr box
= &text
->BoundingBox
;
346 gui
->draw_rect (Crosshair
.GC
,
347 x
+ box
->X1
, y
+ box
->Y1
, x
+ box
->X2
, y
+ box
->Y2
);
350 /* the tmp polygon has n+1 points because the first
351 * and the last one are set to the same coordinates
353 POLYGON_LOOP (layer
);
355 XORPolygon (polygon
, x
, y
);
360 /* draw elements if visible */
361 if (PCB
->PinOn
&& PCB
->ElementOn
)
362 ELEMENT_LOOP (Buffer
->Data
);
364 if (FRONT (element
) || PCB
->InvisibleObjectsOn
)
365 XORDrawElement (element
, x
, y
);
369 /* and the vias, move offset by thickness/2 */
371 VIA_LOOP (Buffer
->Data
);
373 gui
->draw_arc (Crosshair
.GC
,
374 x
+ via
->X
, y
+ via
->Y
,
375 via
->Thickness
/ 2, via
->Thickness
/ 2, 0, 360);
380 /* ---------------------------------------------------------------------------
381 * draws the rubberband to insert points into polygons/lines/...
384 XORDrawInsertPointObject (void)
386 LineTypePtr line
= (LineTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
387 PointTypePtr point
= (PointTypePtr
) Crosshair
.AttachedObject
.Ptr3
;
389 if (Crosshair
.AttachedObject
.Type
!= NO_TYPE
)
391 gui
->draw_line (Crosshair
.GC
,
392 point
->X
, point
->Y
, line
->Point1
.X
, line
->Point1
.Y
);
393 gui
->draw_line (Crosshair
.GC
,
394 point
->X
, point
->Y
, line
->Point2
.X
, line
->Point2
.Y
);
398 /* ---------------------------------------------------------------------------
399 * draws the attached object while in MOVE_MODE or COPY_MODE
402 XORDrawMoveOrCopyObject (void)
404 RubberbandTypePtr ptr
;
406 LocationType dx
= Crosshair
.X
- Crosshair
.AttachedObject
.X
,
407 dy
= Crosshair
.Y
- Crosshair
.AttachedObject
.Y
;
409 switch (Crosshair
.AttachedObject
.Type
)
413 PinTypePtr via
= (PinTypePtr
) Crosshair
.AttachedObject
.Ptr1
;
415 gui
->draw_arc (Crosshair
.GC
,
418 via
->Thickness
/ 2, via
->Thickness
/ 2, 0, 360);
424 LineTypePtr line
= (LineTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
426 XORDrawAttachedLine (line
->Point1
.X
+ dx
, line
->Point1
.Y
+ dy
,
427 line
->Point2
.X
+ dx
, line
->Point2
.Y
+ dy
,
434 ArcTypePtr Arc
= (ArcTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
436 gui
->draw_arc (Crosshair
.GC
,
439 Arc
->Width
, Arc
->Height
, Arc
->StartAngle
, Arc
->Delta
);
445 PolygonTypePtr polygon
=
446 (PolygonTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
448 /* the tmp polygon has n+1 points because the first
449 * and the last one are set to the same coordinates
451 XORPolygon (polygon
, dx
, dy
);
460 line
= (LineTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
461 point
= (PointTypePtr
) Crosshair
.AttachedObject
.Ptr3
;
462 if (point
== &line
->Point1
)
463 XORDrawAttachedLine (point
->X
+ dx
,
464 point
->Y
+ dy
, line
->Point2
.X
,
465 line
->Point2
.Y
, line
->Thickness
);
467 XORDrawAttachedLine (point
->X
+ dx
,
468 point
->Y
+ dy
, line
->Point1
.X
,
469 line
->Point1
.Y
, line
->Thickness
);
473 case POLYGONPOINT_TYPE
:
475 PolygonTypePtr polygon
;
476 PointTypePtr point
, previous
, following
;
478 polygon
= (PolygonTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
479 point
= (PointTypePtr
) Crosshair
.AttachedObject
.Ptr3
;
481 /* get previous and following point */
482 if (point
== polygon
->Points
)
484 previous
= &polygon
->Points
[polygon
->PointN
- 1];
485 following
= point
+ 1;
487 else if (point
== &polygon
->Points
[polygon
->PointN
- 1])
489 previous
= point
- 1;
490 following
= &polygon
->Points
[0];
494 previous
= point
- 1;
495 following
= point
+ 1;
498 /* draw the two segments */
499 gui
->draw_line (Crosshair
.GC
,
501 previous
->Y
, point
->X
+ dx
, point
->Y
+ dy
);
502 gui
->draw_line (Crosshair
.GC
,
504 point
->Y
+ dy
, following
->X
, following
->Y
);
508 case ELEMENTNAME_TYPE
:
510 /* locate the element "mark" and draw an association line from crosshair to it */
511 ElementTypePtr element
=
512 (ElementTypePtr
) Crosshair
.AttachedObject
.Ptr1
;
514 gui
->draw_line (Crosshair
.GC
,
516 element
->MarkY
, Crosshair
.X
, Crosshair
.Y
);
517 /* fall through to move the text as a box outline */
521 TextTypePtr text
= (TextTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
522 BoxTypePtr box
= &text
->BoundingBox
;
523 gui
->draw_rect (Crosshair
.GC
,
525 box
->Y1
+ dy
, box
->X2
+ dx
, box
->Y2
+ dy
);
529 /* pin/pad movements result in moving an element */
533 XORDrawElement ((ElementTypePtr
) Crosshair
.AttachedObject
.Ptr2
, dx
, dy
);
537 /* draw the attached rubberband lines too */
538 i
= Crosshair
.AttachedObject
.RubberbandN
;
539 ptr
= Crosshair
.AttachedObject
.Rubberband
;
542 PointTypePtr point1
, point2
;
544 if (TEST_FLAG (VIAFLAG
, ptr
->Line
))
546 /* this is a rat going to a polygon. do not draw for rubberband */;
548 else if (TEST_FLAG (RUBBERENDFLAG
, ptr
->Line
))
550 /* 'point1' is always the fix-point */
551 if (ptr
->MovedPoint
== &ptr
->Line
->Point1
)
553 point1
= &ptr
->Line
->Point2
;
554 point2
= &ptr
->Line
->Point1
;
558 point1
= &ptr
->Line
->Point1
;
559 point2
= &ptr
->Line
->Point2
;
561 XORDrawAttachedLine (point1
->X
,
562 point1
->Y
, point2
->X
+ dx
,
563 point2
->Y
+ dy
, ptr
->Line
->Thickness
);
565 else if (ptr
->MovedPoint
== &ptr
->Line
->Point1
)
566 XORDrawAttachedLine (ptr
->Line
->Point1
.X
+ dx
,
567 ptr
->Line
->Point1
.Y
+ dy
,
568 ptr
->Line
->Point2
.X
+ dx
,
569 ptr
->Line
->Point2
.Y
+ dy
, ptr
->Line
->Thickness
);
576 /* ---------------------------------------------------------------------------
577 * draws additional stuff that follows the crosshair
580 DrawAttached (Boolean BlockToo
)
583 switch (Settings
.Mode
)
586 gui
->draw_arc (Crosshair
.GC
,
589 Settings
.ViaThickness
/ 2,
590 Settings
.ViaThickness
/ 2, 0, 360);
591 if (TEST_FLAG (SHOWDRCFLAG
, PCB
))
593 s
= Settings
.ViaThickness
/ 2 + PCB
->Bloat
+ 1;
594 gui
->set_color (Crosshair
.GC
, Settings
.CrossColor
);
595 gui
->draw_arc (Crosshair
.GC
,
596 Crosshair
.X
, Crosshair
.Y
, s
, s
, 0, 360);
597 gui
->set_color (Crosshair
.GC
, Settings
.CrosshairColor
);
601 /* the attached line is used by both LINEMODE and POLYGON_MODE */
603 /* draw only if starting point is set */
604 if (Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
605 gui
->draw_line (Crosshair
.GC
,
606 Crosshair
.AttachedLine
.Point1
.X
,
607 Crosshair
.AttachedLine
.Point1
.Y
,
608 Crosshair
.AttachedLine
.Point2
.X
,
609 Crosshair
.AttachedLine
.Point2
.Y
);
611 /* draw attached polygon only if in POLYGON_MODE */
612 if (Crosshair
.AttachedPolygon
.PointN
> 1)
614 XORPolygon (&Crosshair
.AttachedPolygon
, 0, 0);
619 if (Crosshair
.AttachedBox
.State
!= STATE_FIRST
)
621 XORDrawAttachedArc (Settings
.LineThickness
);
622 if (TEST_FLAG (SHOWDRCFLAG
, PCB
))
624 gui
->set_color (Crosshair
.GC
, Settings
.CrossColor
);
625 XORDrawAttachedArc (Settings
.LineThickness
+
626 2 * (PCB
->Bloat
+ 1));
627 gui
->set_color (Crosshair
.GC
, Settings
.CrosshairColor
);
634 /* draw only if starting point exists and the line has length */
635 if (Crosshair
.AttachedLine
.State
!= STATE_FIRST
&&
636 Crosshair
.AttachedLine
.draw
)
638 XORDrawAttachedLine (Crosshair
.AttachedLine
.Point1
.X
,
639 Crosshair
.AttachedLine
.Point1
.Y
,
640 Crosshair
.AttachedLine
.Point2
.X
,
641 Crosshair
.AttachedLine
.Point2
.Y
,
642 PCB
->RatDraw
? 10 : Settings
.LineThickness
);
643 /* draw two lines ? */
645 XORDrawAttachedLine (Crosshair
.AttachedLine
.Point2
.X
,
646 Crosshair
.AttachedLine
.Point2
.Y
,
647 Crosshair
.X
, Crosshair
.Y
,
648 PCB
->RatDraw
? 10 : Settings
.LineThickness
);
649 if (TEST_FLAG (SHOWDRCFLAG
, PCB
))
651 gui
->set_color (Crosshair
.GC
, Settings
.CrossColor
);
652 XORDrawAttachedLine (Crosshair
.AttachedLine
.Point1
.X
,
653 Crosshair
.AttachedLine
.Point1
.Y
,
654 Crosshair
.AttachedLine
.Point2
.X
,
655 Crosshair
.AttachedLine
.Point2
.Y
,
656 PCB
->RatDraw
? 10 : Settings
.LineThickness
657 + 2 * (PCB
->Bloat
+ 1));
659 XORDrawAttachedLine (Crosshair
.AttachedLine
.Point2
.X
,
660 Crosshair
.AttachedLine
.Point2
.Y
,
661 Crosshair
.X
, Crosshair
.Y
,
662 PCB
->RatDraw
? 10 : Settings
.
663 LineThickness
+ 2 * (PCB
->Bloat
+ 1));
664 gui
->set_color (Crosshair
.GC
, Settings
.CrosshairColor
);
669 case PASTEBUFFER_MODE
:
670 XORDrawBuffer (PASTEBUFFER
);
675 XORDrawMoveOrCopyObject ();
678 case INSERTPOINT_MODE
:
679 XORDrawInsertPointObject ();
683 /* an attached box does not depend on a special mode */
684 if (Crosshair
.AttachedBox
.State
== STATE_SECOND
||
685 (BlockToo
&& Crosshair
.AttachedBox
.State
== STATE_THIRD
))
687 LocationType x1
, y1
, x2
, y2
;
689 x1
= Crosshair
.AttachedBox
.Point1
.X
;
690 y1
= Crosshair
.AttachedBox
.Point1
.Y
;
691 x2
= Crosshair
.AttachedBox
.Point2
.X
;
692 y2
= Crosshair
.AttachedBox
.Point2
.Y
;
693 gui
->draw_rect (Crosshair
.GC
, x1
, y1
, x2
, y2
);
697 /* ---------------------------------------------------------------------------
698 * switches crosshair on
701 CrosshairOn (Boolean BlockToo
)
706 DrawAttached (BlockToo
);
711 /* ---------------------------------------------------------------------------
712 * switches crosshair off
715 CrosshairOff (Boolean BlockToo
)
719 Crosshair
.On
= False
;
720 DrawAttached (BlockToo
);
726 * The parameter to HideCrosshair() and RestoreCrosshair() dictates whether
727 * the object you're dragging should be drawn or not.
729 * This argument is _not_ saved in the stack, so whether you have drawings
730 * following the cursor around or not is dependant on the parameter passed
731 * LAST to either of these two functions.
734 /* ---------------------------------------------------------------------------
735 * saves crosshair state (on/off) and hides him
738 HideCrosshair (Boolean BlockToo
)
740 /* fprintf(stderr, "HideCrosshair %d stack %d\n", BlockToo ? 1 : 0, CrosshairStackLocation); */
741 if (CrosshairStackLocation
>= MAX_CROSSHAIRSTACK_DEPTH
)
743 fprintf(stderr
, "Error: CrosshairStackLocation overflow\n");
747 CrosshairStack
[CrosshairStackLocation
] = Crosshair
.On
;
748 CrosshairStackLocation
++;
750 CrosshairOff (BlockToo
);
753 /* ---------------------------------------------------------------------------
754 * restores last crosshair state
757 RestoreCrosshair (Boolean BlockToo
)
759 /* fprintf(stderr, "RestoreCrosshair %d stack %d\n", BlockToo ? 1 : 0, CrosshairStackLocation); */
760 if (CrosshairStackLocation
<= 0)
762 fprintf(stderr
, "Error: CrosshairStackLocation underflow\n");
766 CrosshairStackLocation
--;
768 if (CrosshairStack
[CrosshairStackLocation
])
770 CrosshairOn (BlockToo
);
774 CrosshairOff (BlockToo
);
778 /* ---------------------------------------------------------------------------
779 * recalculates the passed coordinates to fit the current grid setting
782 FitCrosshairIntoGrid (LocationType X
, LocationType Y
)
784 LocationType x2
, y2
, x0
, y0
;
785 void *ptr1
, *ptr2
, *ptr3
;
792 Crosshair
.X
= MIN (Crosshair
.MaxX
, MAX (Crosshair
.MinX
, X
));
793 Crosshair
.Y
= MIN (Crosshair
.MaxY
, MAX (Crosshair
.MinY
, Y
));
795 if (PCB
->RatDraw
|| TEST_FLAG (SNAPPINFLAG
, PCB
))
798 SearchScreen (Crosshair
.X
, Crosshair
.Y
,
799 PAD_TYPE
| PIN_TYPE
, &ptr1
, &ptr2
, &ptr3
);
800 if (ans
== NO_TYPE
&& !PCB
->RatDraw
)
802 SearchScreen (Crosshair
.X
, Crosshair
.Y
, VIA_TYPE
| LINEPOINT_TYPE
,
803 &ptr1
, &ptr2
, &ptr3
);
804 if (ans
== NO_TYPE
&& !PCB
->RatDraw
)
806 SearchScreen (Crosshair
.X
, Crosshair
.Y
, ELEMENT_TYPE
, &ptr1
, &ptr2
,
812 /* avoid self-snapping */
813 if (Settings
.Mode
== MOVE_MODE
)
815 switch (Crosshair
.AttachedObject
.Type
)
818 if ((ans
& (PAD_TYPE
| PIN_TYPE
)) &&
819 ptr1
== Crosshair
.AttachedObject
.Ptr1
)
823 /* just avoid snapping to any other vias */
837 /* check if new position is inside the output window
838 * This might not be true after the window has been resized.
839 * In this case we just set it to the center of the window or
840 * with respect to the grid (if possible)
842 if (Crosshair
.X
< x0
|| Crosshair
.X
> x2
)
844 if (x2
+ 1 >= PCB
->Grid
)
845 /* there must be a point that matches the grid
846 * so we just have to look for it with some integer
849 x0
= GRIDFIT_X (PCB
->Grid
, PCB
->Grid
);
854 /* check if the new position matches the grid */
855 x0
= GRIDFIT_X (Crosshair
.X
, PCB
->Grid
);
857 /* do the same for the second coordinate */
858 if (Crosshair
.Y
< y0
|| Crosshair
.Y
> y2
)
860 if (y2
+ 1 >= PCB
->Grid
)
861 y0
= GRIDFIT_Y (PCB
->Grid
, PCB
->Grid
);
866 y0
= GRIDFIT_Y (Crosshair
.Y
, PCB
->Grid
);
868 if (Marked
.status
&& TEST_FLAG (ORTHOMOVEFLAG
, PCB
))
870 int dx
= Crosshair
.X
- Marked
.X
;
871 int dy
= Crosshair
.Y
- Marked
.Y
;
872 if (ABS (dx
) > ABS (dy
))
881 PadTypePtr pad
= (PadTypePtr
) ptr2
;
883 if (SQUARE (pad
->Point1
.X
- Crosshair
.X
) +
884 SQUARE (pad
->Point1
.Y
- Crosshair
.Y
) <
885 SQUARE (pad
->Point2
.X
- Crosshair
.X
) + SQUARE (pad
->Point2
.Y
-
897 if (!gui
->shift_is_pressed()
898 || (SQUARE (x0
- Crosshair
.X
) + SQUARE (y0
- Crosshair
.Y
) >
899 SQUARE (px
- Crosshair
.X
) + SQUARE (py
- Crosshair
.Y
)))
906 else if (ans
& (PIN_TYPE
| VIA_TYPE
))
908 PinTypePtr pin
= (PinTypePtr
) ptr2
;
909 if (!gui
->shift_is_pressed()
910 || (SQUARE (x0
- Crosshair
.X
) +
911 SQUARE (y0
- Crosshair
.Y
) >
912 SQUARE (pin
->X
- Crosshair
.X
) + SQUARE (pin
->Y
- Crosshair
.Y
)))
918 else if (ans
& LINEPOINT_TYPE
)
920 PointTypePtr pnt
= (PointTypePtr
) ptr3
;
921 if (((x0
- Crosshair
.X
) * (x0
- Crosshair
.X
) +
922 (y0
- Crosshair
.Y
) * (y0
- Crosshair
.Y
)) >
923 ((pnt
->X
- Crosshair
.X
) * (pnt
->X
- Crosshair
.X
) +
924 (pnt
->Y
- Crosshair
.Y
) * (pnt
->Y
- Crosshair
.Y
)))
930 else if (ans
& ELEMENT_TYPE
)
932 ElementTypePtr el
= (ElementTypePtr
) ptr1
;
933 if (SQUARE (x0
- Crosshair
.X
) + SQUARE (y0
- Crosshair
.Y
) >
934 SQUARE (el
->MarkX
- Crosshair
.X
) + SQUARE (el
->MarkY
- Crosshair
.Y
))
940 if (x0
>= 0 && y0
>= 0)
945 if (Settings
.Mode
== ARROW_MODE
)
948 SearchScreen (Crosshair
.X
, Crosshair
.Y
, LINEPOINT_TYPE
,
949 &ptr1
, &ptr2
, &ptr3
);
951 hid_action("PointCursor");
952 else if (!TEST_FLAG(SELECTEDFLAG
, (LineType
*)ptr2
))
953 hid_actionl("PointCursor","True", NULL
);
955 if (Settings
.Mode
== LINE_MODE
956 && Crosshair
.AttachedLine
.State
!= STATE_FIRST
957 && TEST_FLAG (AUTODRCFLAG
, PCB
))
960 gui
->set_crosshair (Crosshair
.X
, Crosshair
.Y
, HID_SC_DO_NOTHING
);
963 /* ---------------------------------------------------------------------------
964 * move crosshair relative (has to be switched off)
967 MoveCrosshairRelative (LocationType DeltaX
, LocationType DeltaY
)
969 FitCrosshairIntoGrid (Crosshair
.X
+ DeltaX
, Crosshair
.Y
+ DeltaY
);
972 /* ---------------------------------------------------------------------------
973 * move crosshair absolute switched off if it moved
974 * return True if it switched off
977 MoveCrosshairAbsolute (LocationType X
, LocationType Y
)
979 LocationType x
, y
, z
;
982 FitCrosshairIntoGrid (X
, Y
);
983 if (Crosshair
.X
!= x
|| Crosshair
.Y
!= y
)
985 /* back up to old position and erase crosshair */
991 HideCrosshair (False
);
992 /* now move forward again */
1000 /* ---------------------------------------------------------------------------
1001 * sets the valid range for the crosshair cursor
1004 SetCrosshairRange (LocationType MinX
, LocationType MinY
, LocationType MaxX
,
1007 Crosshair
.MinX
= MAX (0, MinX
);
1008 Crosshair
.MinY
= MAX (0, MinY
);
1009 Crosshair
.MaxX
= MIN ((LocationType
) PCB
->MaxWidth
, MaxX
);
1010 Crosshair
.MaxY
= MIN ((LocationType
) PCB
->MaxHeight
, MaxY
);
1012 /* force update of position */
1013 MoveCrosshairRelative (0, 0);
1016 /* --------------------------------------------------------------------------
1017 * draw the marker position
1018 * if argument is True, draw only if it is visible, otherwise draw it regardless
1021 DrawMark (Boolean ifvis
)
1023 if (Marked
.status
|| !ifvis
)
1025 gui
->draw_line (Crosshair
.GC
,
1026 Marked
.X
- MARK_SIZE
,
1027 Marked
.Y
- MARK_SIZE
,
1028 Marked
.X
+ MARK_SIZE
, Marked
.Y
+ MARK_SIZE
);
1029 gui
->draw_line (Crosshair
.GC
,
1030 Marked
.X
+ MARK_SIZE
,
1031 Marked
.Y
- MARK_SIZE
,
1032 Marked
.X
- MARK_SIZE
, Marked
.Y
+ MARK_SIZE
);
1036 /* ---------------------------------------------------------------------------
1037 * initializes crosshair stuff
1038 * clears the struct, allocates to graphical contexts and
1039 * initializes the stack
1042 InitCrosshair (void)
1044 Crosshair
.GC
= gui
->make_gc ();
1046 gui
->set_color (Crosshair
.GC
, Settings
.CrosshairColor
);
1047 gui
->set_draw_xor (Crosshair
.GC
, 1);
1048 gui
->set_line_cap (Crosshair
.GC
, Trace_Cap
);
1049 gui
->set_line_width (Crosshair
.GC
, 1);
1051 /* fake a crosshair off entry on stack */
1052 CrosshairStackLocation
= 0;
1053 CrosshairStack
[CrosshairStackLocation
++] = True
;
1054 Crosshair
.On
= False
;
1056 /* set initial shape */
1057 Crosshair
.shape
= Basic_Crosshair_Shape
;
1059 /* set default limits */
1060 Crosshair
.MinX
= Crosshair
.MinY
= 0;
1061 Crosshair
.MaxX
= PCB
->MaxWidth
;
1062 Crosshair
.MaxY
= PCB
->MaxHeight
;
1064 /* clear the mark */
1065 Marked
.status
= False
;
1068 /* ---------------------------------------------------------------------------
1069 * exits crosshair routines, release GCs
1072 DestroyCrosshair (void)
1074 CrosshairOff (True
);
1075 FreePolygonMemory (&Crosshair
.AttachedPolygon
);
1076 gui
->destroy_gc (Crosshair
.GC
);