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"
53 #ifdef HAVE_LIBDMALLOC
60 #define ABS(x) (((x)<0)?-(x):(x))
68 /* ---------------------------------------------------------------------------
69 * some local identifiers
72 /* This is a stack for HideCrosshair() and RestoreCrosshair() calls. They
73 * must always be matched. */
74 static bool CrosshairStack
[MAX_CROSSHAIRSTACK_DEPTH
];
75 static int CrosshairStackLocation
= 0;
77 /* ---------------------------------------------------------------------------
78 * some local prototypes
80 static void XORPolygon (PolygonTypePtr
, LocationType
, LocationType
);
81 static void XORDrawElement (ElementTypePtr
, LocationType
, LocationType
);
82 static void XORDrawBuffer (BufferTypePtr
);
83 static void XORDrawInsertPointObject (void);
84 static void XORDrawMoveOrCopyObject (void);
85 static void XORDrawAttachedLine (LocationType
, LocationType
, LocationType
,
86 LocationType
, BDimension
);
87 static void XORDrawAttachedArc (BDimension
);
88 static void DrawAttached (bool);
90 /* ---------------------------------------------------------------------------
91 * creates a tmp polygon with coordinates converted to screen system
94 XORPolygon (PolygonTypePtr polygon
, LocationType dx
, LocationType dy
)
97 for (i
= 0; i
< polygon
->PointN
; i
++)
99 Cardinal next
= next_contour_point (polygon
, i
);
100 gui
->draw_line (Crosshair
.GC
,
101 polygon
->Points
[i
].X
+ dx
,
102 polygon
->Points
[i
].Y
+ dy
,
103 polygon
->Points
[next
].X
+ dx
,
104 polygon
->Points
[next
].Y
+ dy
);
108 /*-----------------------------------------------------------
109 * Draws the outline of an arc
112 XORDrawAttachedArc (BDimension thick
)
118 BDimension wid
= thick
/ 2;
120 wx
= Crosshair
.X
- Crosshair
.AttachedBox
.Point1
.X
;
121 wy
= Crosshair
.Y
- Crosshair
.AttachedBox
.Point1
.Y
;
122 if (wx
== 0 && wy
== 0)
124 arc
.X
= Crosshair
.AttachedBox
.Point1
.X
;
125 arc
.Y
= Crosshair
.AttachedBox
.Point1
.Y
;
126 if (XOR (Crosshair
.AttachedBox
.otherway
, abs (wy
) > abs (wx
)))
128 arc
.X
= Crosshair
.AttachedBox
.Point1
.X
+ abs (wy
) * SGNZ (wx
);
129 sa
= (wx
>= 0) ? 0 : 180;
131 if (abs (wy
) >= 2 * abs (wx
))
132 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? 45 : -45;
135 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? 90 : -90;
139 arc
.Y
= Crosshair
.AttachedBox
.Point1
.Y
+ abs (wx
) * SGNZ (wy
);
140 sa
= (wy
>= 0) ? -90 : 90;
142 if (abs (wx
) >= 2 * abs (wy
))
143 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? -45 : 45;
146 dir
= (SGNZ (wx
) == SGNZ (wy
)) ? -90 : 90;
152 arc
.Width
= arc
.Height
= wy
;
153 bx
= GetArcEnds (&arc
);
155 gui
->draw_arc (Crosshair
.GC
, arc
.X
, arc
.Y
, wy
+ wid
, wy
+ wid
, sa
, dir
);
156 if (wid
> pixel_slop
)
158 gui
->draw_arc (Crosshair
.GC
, arc
.X
, arc
.Y
, wy
- wid
, wy
- wid
, sa
, dir
);
159 gui
->draw_arc (Crosshair
.GC
, bx
->X1
, bx
->Y1
,
160 wid
, wid
, sa
, -180 * SGN (dir
));
161 gui
->draw_arc (Crosshair
.GC
, bx
->X2
, bx
->Y2
,
162 wid
, wid
, sa
+ dir
, 180 * SGN (dir
));
166 /*-----------------------------------------------------------
167 * Draws the outline of a line
170 XORDrawAttachedLine (LocationType x1
, LocationType y1
, LocationType x2
,
171 LocationType y2
, BDimension thick
)
173 LocationType dx
, dy
, ox
, oy
;
178 if (dx
!= 0 || dy
!= 0)
179 h
= 0.5 * thick
/ sqrt (SQUARE (dx
) + SQUARE (dy
));
182 ox
= dy
* h
+ 0.5 * SGN (dy
);
183 oy
= -(dx
* h
+ 0.5 * SGN (dx
));
184 gui
->draw_line (Crosshair
.GC
, x1
+ ox
, y1
+ oy
, x2
+ ox
, y2
+ oy
);
185 if (abs (ox
) >= pixel_slop
|| abs (oy
) >= pixel_slop
)
187 LocationType angle
= atan2 ((float) dx
, (float) dy
) * 57.295779;
188 gui
->draw_line (Crosshair
.GC
, x1
- ox
, y1
- oy
, x2
- ox
, y2
- oy
);
189 gui
->draw_arc (Crosshair
.GC
,
190 x1
, y1
, thick
/ 2, thick
/ 2, angle
- 180, 180);
191 gui
->draw_arc (Crosshair
.GC
, x2
, y2
, thick
/ 2, thick
/ 2, angle
, 180);
195 /* ---------------------------------------------------------------------------
196 * draws the elements of a loaded circuit which is to be merged in
199 XORDrawElement (ElementTypePtr Element
, LocationType DX
, LocationType DY
)
201 /* if no silkscreen, draw the bounding box */
202 if (Element
->ArcN
== 0 && Element
->LineN
== 0)
204 gui
->draw_line (Crosshair
.GC
,
205 DX
+ Element
->BoundingBox
.X1
,
206 DY
+ Element
->BoundingBox
.Y1
,
207 DX
+ Element
->BoundingBox
.X1
,
208 DY
+ Element
->BoundingBox
.Y2
);
209 gui
->draw_line (Crosshair
.GC
,
210 DX
+ Element
->BoundingBox
.X1
,
211 DY
+ Element
->BoundingBox
.Y2
,
212 DX
+ Element
->BoundingBox
.X2
,
213 DY
+ Element
->BoundingBox
.Y2
);
214 gui
->draw_line (Crosshair
.GC
,
215 DX
+ Element
->BoundingBox
.X2
,
216 DY
+ Element
->BoundingBox
.Y2
,
217 DX
+ Element
->BoundingBox
.X2
,
218 DY
+ Element
->BoundingBox
.Y1
);
219 gui
->draw_line (Crosshair
.GC
,
220 DX
+ Element
->BoundingBox
.X2
,
221 DY
+ Element
->BoundingBox
.Y1
,
222 DX
+ Element
->BoundingBox
.X1
,
223 DY
+ Element
->BoundingBox
.Y1
);
227 ELEMENTLINE_LOOP (Element
);
229 gui
->draw_line (Crosshair
.GC
,
232 DX
+ line
->Point2
.X
, DY
+ line
->Point2
.Y
);
236 /* arc coordinates and angles have to be converted to X11 notation */
239 gui
->draw_arc (Crosshair
.GC
,
242 arc
->Width
, arc
->Height
, arc
->StartAngle
, arc
->Delta
);
246 /* pin coordinates and angles have to be converted to X11 notation */
249 gui
->draw_arc (Crosshair
.GC
,
252 pin
->Thickness
/ 2, pin
->Thickness
/ 2, 0, 360);
259 if ((TEST_FLAG (ONSOLDERFLAG
, pad
) != 0) ==
260 Settings
.ShowSolderSide
|| PCB
->InvisibleObjectsOn
)
262 if (pad
->Point1
.X
== pad
->Point2
.X
263 || pad
->Point1
.Y
== pad
->Point2
.Y
)
265 int minx
, miny
, maxx
, maxy
;
266 minx
= DX
+ MIN (pad
->Point1
.X
, pad
->Point2
.X
) - pad
->Thickness
/2;
267 maxx
= DX
+ MAX (pad
->Point1
.X
, pad
->Point2
.X
) + pad
->Thickness
/2;
268 miny
= DY
+ MIN (pad
->Point1
.Y
, pad
->Point2
.Y
) - pad
->Thickness
/2;
269 maxy
= DY
+ MAX (pad
->Point1
.Y
, pad
->Point2
.Y
) + pad
->Thickness
/2;
270 gui
->draw_line (Crosshair
.GC
, minx
, miny
, maxx
, miny
);
271 gui
->draw_line (Crosshair
.GC
, minx
, miny
, minx
, maxy
);
272 gui
->draw_line (Crosshair
.GC
, maxx
, miny
, maxx
, maxy
);
273 gui
->draw_line (Crosshair
.GC
, minx
, maxy
, maxx
, maxy
);
277 /* FIXME: draw outlines, not centerlines. */
278 gui
->draw_line (Crosshair
.GC
,
279 DX
+ pad
->Point1
.X
, DY
+ pad
->Point1
.Y
,
280 DX
+ pad
->Point2
.X
, DY
+ pad
->Point2
.Y
);
286 gui
->draw_line (Crosshair
.GC
,
287 Element
->MarkX
+ DX
- EMARK_SIZE
,
289 Element
->MarkX
+ DX
, Element
->MarkY
+ DY
- EMARK_SIZE
);
290 gui
->draw_line (Crosshair
.GC
,
291 Element
->MarkX
+ DX
+ EMARK_SIZE
,
293 Element
->MarkX
+ DX
, Element
->MarkY
+ DY
- EMARK_SIZE
);
294 gui
->draw_line (Crosshair
.GC
,
295 Element
->MarkX
+ DX
- EMARK_SIZE
,
297 Element
->MarkX
+ DX
, Element
->MarkY
+ DY
+ EMARK_SIZE
);
298 gui
->draw_line (Crosshair
.GC
,
299 Element
->MarkX
+ DX
+ EMARK_SIZE
,
301 Element
->MarkX
+ DX
, Element
->MarkY
+ DY
+ EMARK_SIZE
);
304 /* ---------------------------------------------------------------------------
305 * draws all visible and attached objects of the pastebuffer
308 XORDrawBuffer (BufferTypePtr Buffer
)
314 x
= Crosshair
.X
- Buffer
->X
;
315 y
= Crosshair
.Y
- Buffer
->Y
;
317 /* draw all visible layers */
318 for (i
= 0; i
< max_layer
+ 2; i
++)
319 if (PCB
->Data
->Layer
[i
].On
)
321 LayerTypePtr layer
= &Buffer
->Data
->Layer
[i
];
326 XORDrawAttachedLine(x +line->Point1.X,
327 y +line->Point1.Y, x +line->Point2.X,
328 y +line->Point2.Y, line->Thickness);
330 gui
->draw_line (Crosshair
.GC
,
331 x
+ line
->Point1
.X
, y
+ line
->Point1
.Y
,
332 x
+ line
->Point2
.X
, y
+ line
->Point2
.Y
);
337 gui
->draw_arc (Crosshair
.GC
,
341 arc
->Height
, arc
->StartAngle
, arc
->Delta
);
346 BoxTypePtr box
= &text
->BoundingBox
;
347 gui
->draw_rect (Crosshair
.GC
,
348 x
+ box
->X1
, y
+ box
->Y1
, x
+ box
->X2
, y
+ box
->Y2
);
351 /* the tmp polygon has n+1 points because the first
352 * and the last one are set to the same coordinates
354 POLYGON_LOOP (layer
);
356 XORPolygon (polygon
, x
, y
);
361 /* draw elements if visible */
362 if (PCB
->PinOn
&& PCB
->ElementOn
)
363 ELEMENT_LOOP (Buffer
->Data
);
365 if (FRONT (element
) || PCB
->InvisibleObjectsOn
)
366 XORDrawElement (element
, x
, y
);
370 /* and the vias, move offset by thickness/2 */
372 VIA_LOOP (Buffer
->Data
);
374 gui
->draw_arc (Crosshair
.GC
,
375 x
+ via
->X
, y
+ via
->Y
,
376 via
->Thickness
/ 2, via
->Thickness
/ 2, 0, 360);
381 /* ---------------------------------------------------------------------------
382 * draws the rubberband to insert points into polygons/lines/...
385 XORDrawInsertPointObject (void)
387 LineTypePtr line
= (LineTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
388 PointTypePtr point
= (PointTypePtr
) Crosshair
.AttachedObject
.Ptr3
;
390 if (Crosshair
.AttachedObject
.Type
!= NO_TYPE
)
392 gui
->draw_line (Crosshair
.GC
,
393 point
->X
, point
->Y
, line
->Point1
.X
, line
->Point1
.Y
);
394 gui
->draw_line (Crosshair
.GC
,
395 point
->X
, point
->Y
, line
->Point2
.X
, line
->Point2
.Y
);
399 /* ---------------------------------------------------------------------------
400 * draws the attached object while in MOVE_MODE or COPY_MODE
403 XORDrawMoveOrCopyObject (void)
405 RubberbandTypePtr ptr
;
407 LocationType dx
= Crosshair
.X
- Crosshair
.AttachedObject
.X
,
408 dy
= Crosshair
.Y
- Crosshair
.AttachedObject
.Y
;
410 switch (Crosshair
.AttachedObject
.Type
)
414 PinTypePtr via
= (PinTypePtr
) Crosshair
.AttachedObject
.Ptr1
;
416 gui
->draw_arc (Crosshair
.GC
,
419 via
->Thickness
/ 2, via
->Thickness
/ 2, 0, 360);
425 LineTypePtr line
= (LineTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
427 XORDrawAttachedLine (line
->Point1
.X
+ dx
, line
->Point1
.Y
+ dy
,
428 line
->Point2
.X
+ dx
, line
->Point2
.Y
+ dy
,
435 ArcTypePtr Arc
= (ArcTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
437 gui
->draw_arc (Crosshair
.GC
,
440 Arc
->Width
, Arc
->Height
, Arc
->StartAngle
, Arc
->Delta
);
446 PolygonTypePtr polygon
=
447 (PolygonTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
449 /* the tmp polygon has n+1 points because the first
450 * and the last one are set to the same coordinates
452 XORPolygon (polygon
, dx
, dy
);
461 line
= (LineTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
462 point
= (PointTypePtr
) Crosshair
.AttachedObject
.Ptr3
;
463 if (point
== &line
->Point1
)
464 XORDrawAttachedLine (point
->X
+ dx
,
465 point
->Y
+ dy
, line
->Point2
.X
,
466 line
->Point2
.Y
, line
->Thickness
);
468 XORDrawAttachedLine (point
->X
+ dx
,
469 point
->Y
+ dy
, line
->Point1
.X
,
470 line
->Point1
.Y
, line
->Thickness
);
474 case POLYGONPOINT_TYPE
:
476 PolygonTypePtr polygon
;
478 Cardinal point_idx
, prev
, next
;
480 polygon
= (PolygonTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
481 point
= (PointTypePtr
) Crosshair
.AttachedObject
.Ptr3
;
482 point_idx
= polygon_point_idx (polygon
, point
);
484 /* get previous and following point */
485 prev
= prev_contour_point (polygon
, point_idx
);
486 next
= next_contour_point (polygon
, point_idx
);
488 /* draw the two segments */
489 gui
->draw_line (Crosshair
.GC
,
490 polygon
->Points
[prev
].X
, polygon
->Points
[prev
].Y
,
491 point
->X
+ dx
, point
->Y
+ dy
);
492 gui
->draw_line (Crosshair
.GC
,
493 point
->X
+ dx
, point
->Y
+ dy
,
494 polygon
->Points
[next
].X
, polygon
->Points
[next
].Y
);
498 case ELEMENTNAME_TYPE
:
500 /* locate the element "mark" and draw an association line from crosshair to it */
501 ElementTypePtr element
=
502 (ElementTypePtr
) Crosshair
.AttachedObject
.Ptr1
;
504 gui
->draw_line (Crosshair
.GC
,
506 element
->MarkY
, Crosshair
.X
, Crosshair
.Y
);
507 /* fall through to move the text as a box outline */
511 TextTypePtr text
= (TextTypePtr
) Crosshair
.AttachedObject
.Ptr2
;
512 BoxTypePtr box
= &text
->BoundingBox
;
513 gui
->draw_rect (Crosshair
.GC
,
515 box
->Y1
+ dy
, box
->X2
+ dx
, box
->Y2
+ dy
);
519 /* pin/pad movements result in moving an element */
523 XORDrawElement ((ElementTypePtr
) Crosshair
.AttachedObject
.Ptr2
, dx
, dy
);
527 /* draw the attached rubberband lines too */
528 i
= Crosshair
.AttachedObject
.RubberbandN
;
529 ptr
= Crosshair
.AttachedObject
.Rubberband
;
532 PointTypePtr point1
, point2
;
534 if (TEST_FLAG (VIAFLAG
, ptr
->Line
))
536 /* this is a rat going to a polygon. do not draw for rubberband */;
538 else if (TEST_FLAG (RUBBERENDFLAG
, ptr
->Line
))
540 /* 'point1' is always the fix-point */
541 if (ptr
->MovedPoint
== &ptr
->Line
->Point1
)
543 point1
= &ptr
->Line
->Point2
;
544 point2
= &ptr
->Line
->Point1
;
548 point1
= &ptr
->Line
->Point1
;
549 point2
= &ptr
->Line
->Point2
;
551 XORDrawAttachedLine (point1
->X
,
552 point1
->Y
, point2
->X
+ dx
,
553 point2
->Y
+ dy
, ptr
->Line
->Thickness
);
555 else if (ptr
->MovedPoint
== &ptr
->Line
->Point1
)
556 XORDrawAttachedLine (ptr
->Line
->Point1
.X
+ dx
,
557 ptr
->Line
->Point1
.Y
+ dy
,
558 ptr
->Line
->Point2
.X
+ dx
,
559 ptr
->Line
->Point2
.Y
+ dy
, ptr
->Line
->Thickness
);
566 /* ---------------------------------------------------------------------------
567 * draws additional stuff that follows the crosshair
570 DrawAttached (bool BlockToo
)
573 switch (Settings
.Mode
)
576 gui
->draw_arc (Crosshair
.GC
,
579 Settings
.ViaThickness
/ 2,
580 Settings
.ViaThickness
/ 2, 0, 360);
581 if (TEST_FLAG (SHOWDRCFLAG
, PCB
))
583 s
= Settings
.ViaThickness
/ 2 + PCB
->Bloat
+ 1;
584 gui
->set_color (Crosshair
.GC
, Settings
.CrossColor
);
585 gui
->draw_arc (Crosshair
.GC
,
586 Crosshair
.X
, Crosshair
.Y
, s
, s
, 0, 360);
587 gui
->set_color (Crosshair
.GC
, Settings
.CrosshairColor
);
591 /* the attached line is used by both LINEMODE, POLYGON_MODE and POLYGONHOLE_MODE*/
593 case POLYGONHOLE_MODE
:
594 /* draw only if starting point is set */
595 if (Crosshair
.AttachedLine
.State
!= STATE_FIRST
)
596 gui
->draw_line (Crosshair
.GC
,
597 Crosshair
.AttachedLine
.Point1
.X
,
598 Crosshair
.AttachedLine
.Point1
.Y
,
599 Crosshair
.AttachedLine
.Point2
.X
,
600 Crosshair
.AttachedLine
.Point2
.Y
);
602 /* draw attached polygon only if in POLYGON_MODE or POLYGONHOLE_MODE */
603 if (Crosshair
.AttachedPolygon
.PointN
> 1)
605 XORPolygon (&Crosshair
.AttachedPolygon
, 0, 0);
610 if (Crosshair
.AttachedBox
.State
!= STATE_FIRST
)
612 XORDrawAttachedArc (Settings
.LineThickness
);
613 if (TEST_FLAG (SHOWDRCFLAG
, PCB
))
615 gui
->set_color (Crosshair
.GC
, Settings
.CrossColor
);
616 XORDrawAttachedArc (Settings
.LineThickness
+
617 2 * (PCB
->Bloat
+ 1));
618 gui
->set_color (Crosshair
.GC
, Settings
.CrosshairColor
);
625 /* draw only if starting point exists and the line has length */
626 if (Crosshair
.AttachedLine
.State
!= STATE_FIRST
&&
627 Crosshair
.AttachedLine
.draw
)
629 XORDrawAttachedLine (Crosshair
.AttachedLine
.Point1
.X
,
630 Crosshair
.AttachedLine
.Point1
.Y
,
631 Crosshair
.AttachedLine
.Point2
.X
,
632 Crosshair
.AttachedLine
.Point2
.Y
,
633 PCB
->RatDraw
? 10 : Settings
.LineThickness
);
634 /* draw two lines ? */
636 XORDrawAttachedLine (Crosshair
.AttachedLine
.Point2
.X
,
637 Crosshair
.AttachedLine
.Point2
.Y
,
638 Crosshair
.X
, Crosshair
.Y
,
639 PCB
->RatDraw
? 10 : Settings
.LineThickness
);
640 if (TEST_FLAG (SHOWDRCFLAG
, PCB
))
642 gui
->set_color (Crosshair
.GC
, Settings
.CrossColor
);
643 XORDrawAttachedLine (Crosshair
.AttachedLine
.Point1
.X
,
644 Crosshair
.AttachedLine
.Point1
.Y
,
645 Crosshair
.AttachedLine
.Point2
.X
,
646 Crosshair
.AttachedLine
.Point2
.Y
,
647 PCB
->RatDraw
? 10 : Settings
.LineThickness
648 + 2 * (PCB
->Bloat
+ 1));
650 XORDrawAttachedLine (Crosshair
.AttachedLine
.Point2
.X
,
651 Crosshair
.AttachedLine
.Point2
.Y
,
652 Crosshair
.X
, Crosshair
.Y
,
653 PCB
->RatDraw
? 10 : Settings
.
654 LineThickness
+ 2 * (PCB
->Bloat
+ 1));
655 gui
->set_color (Crosshair
.GC
, Settings
.CrosshairColor
);
660 case PASTEBUFFER_MODE
:
661 XORDrawBuffer (PASTEBUFFER
);
666 XORDrawMoveOrCopyObject ();
669 case INSERTPOINT_MODE
:
670 XORDrawInsertPointObject ();
674 /* an attached box does not depend on a special mode */
675 if (Crosshair
.AttachedBox
.State
== STATE_SECOND
||
676 (BlockToo
&& Crosshair
.AttachedBox
.State
== STATE_THIRD
))
678 LocationType x1
, y1
, x2
, y2
;
680 x1
= Crosshair
.AttachedBox
.Point1
.X
;
681 y1
= Crosshair
.AttachedBox
.Point1
.Y
;
682 x2
= Crosshair
.AttachedBox
.Point2
.X
;
683 y2
= Crosshair
.AttachedBox
.Point2
.Y
;
684 gui
->draw_rect (Crosshair
.GC
, x1
, y1
, x2
, y2
);
688 /* ---------------------------------------------------------------------------
689 * switches crosshair on
692 CrosshairOn (bool BlockToo
)
697 DrawAttached (BlockToo
);
702 /* ---------------------------------------------------------------------------
703 * switches crosshair off
706 CrosshairOff (bool BlockToo
)
710 Crosshair
.On
= false;
711 DrawAttached (BlockToo
);
717 * The parameter to HideCrosshair() and RestoreCrosshair() dictates whether
718 * the object you're dragging should be drawn or not.
720 * This argument is _not_ saved in the stack, so whether you have drawings
721 * following the cursor around or not is dependant on the parameter passed
722 * LAST to either of these two functions.
725 /* ---------------------------------------------------------------------------
726 * saves crosshair state (on/off) and hides him
729 HideCrosshair (bool BlockToo
)
731 /* fprintf(stderr, "HideCrosshair %d stack %d\n", BlockToo ? 1 : 0, CrosshairStackLocation); */
732 if (CrosshairStackLocation
>= MAX_CROSSHAIRSTACK_DEPTH
)
734 fprintf(stderr
, "Error: CrosshairStackLocation overflow\n");
738 CrosshairStack
[CrosshairStackLocation
] = Crosshair
.On
;
739 CrosshairStackLocation
++;
741 CrosshairOff (BlockToo
);
744 /* ---------------------------------------------------------------------------
745 * restores last crosshair state
748 RestoreCrosshair (bool BlockToo
)
750 /* fprintf(stderr, "RestoreCrosshair %d stack %d\n", BlockToo ? 1 : 0, CrosshairStackLocation); */
751 if (CrosshairStackLocation
<= 0)
753 fprintf(stderr
, "Error: CrosshairStackLocation underflow\n");
757 CrosshairStackLocation
--;
759 if (CrosshairStack
[CrosshairStackLocation
])
761 CrosshairOn (BlockToo
);
765 CrosshairOff (BlockToo
);
769 /* ---------------------------------------------------------------------------
770 * recalculates the passed coordinates to fit the current grid setting
773 FitCrosshairIntoGrid (LocationType X
, LocationType Y
)
775 LocationType x2
, y2
, x0
, y0
;
776 void *ptr1
, *ptr2
, *ptr3
;
783 Crosshair
.X
= MIN (Crosshair
.MaxX
, MAX (Crosshair
.MinX
, X
));
784 Crosshair
.Y
= MIN (Crosshair
.MaxY
, MAX (Crosshair
.MinY
, Y
));
786 if (PCB
->RatDraw
|| TEST_FLAG (SNAPPINFLAG
, PCB
))
789 SearchScreen (Crosshair
.X
, Crosshair
.Y
,
790 PAD_TYPE
| PIN_TYPE
, &ptr1
, &ptr2
, &ptr3
);
791 if (ans
== NO_TYPE
&& !PCB
->RatDraw
)
793 SearchScreen (Crosshair
.X
, Crosshair
.Y
, VIA_TYPE
| LINEPOINT_TYPE
,
794 &ptr1
, &ptr2
, &ptr3
);
795 if (ans
== NO_TYPE
&& !PCB
->RatDraw
)
797 SearchScreen (Crosshair
.X
, Crosshair
.Y
, ELEMENT_TYPE
, &ptr1
, &ptr2
,
803 /* avoid self-snapping */
804 if (Settings
.Mode
== MOVE_MODE
)
806 switch (Crosshair
.AttachedObject
.Type
)
809 if ((ans
& (PAD_TYPE
| PIN_TYPE
)) &&
810 ptr1
== Crosshair
.AttachedObject
.Ptr1
)
814 /* just avoid snapping to any other vias */
828 /* check if new position is inside the output window
829 * This might not be true after the window has been resized.
830 * In this case we just set it to the center of the window or
831 * with respect to the grid (if possible)
833 if (Crosshair
.X
< x0
|| Crosshair
.X
> x2
)
835 if (x2
+ 1 >= PCB
->Grid
)
836 /* there must be a point that matches the grid
837 * so we just have to look for it with some integer
840 x0
= GRIDFIT_X (PCB
->Grid
, PCB
->Grid
);
845 /* check if the new position matches the grid */
846 x0
= GRIDFIT_X (Crosshair
.X
, PCB
->Grid
);
848 /* do the same for the second coordinate */
849 if (Crosshair
.Y
< y0
|| Crosshair
.Y
> y2
)
851 if (y2
+ 1 >= PCB
->Grid
)
852 y0
= GRIDFIT_Y (PCB
->Grid
, PCB
->Grid
);
857 y0
= GRIDFIT_Y (Crosshair
.Y
, PCB
->Grid
);
859 if (Marked
.status
&& TEST_FLAG (ORTHOMOVEFLAG
, PCB
))
861 int dx
= Crosshair
.X
- Marked
.X
;
862 int dy
= Crosshair
.Y
- Marked
.Y
;
863 if (ABS (dx
) > ABS (dy
))
872 PadTypePtr pad
= (PadTypePtr
) ptr2
;
875 px
= (pad
->Point1
.X
+ pad
->Point2
.X
) / 2;
876 py
= (pad
->Point1
.Y
+ pad
->Point2
.Y
) / 2;
878 if (!gui
->shift_is_pressed()
879 || (SQUARE (x0
- Crosshair
.X
) + SQUARE (y0
- Crosshair
.Y
) >
880 SQUARE (px
- Crosshair
.X
) + SQUARE (py
- Crosshair
.Y
)))
887 else if (ans
& (PIN_TYPE
| VIA_TYPE
))
889 PinTypePtr pin
= (PinTypePtr
) ptr2
;
890 if (!gui
->shift_is_pressed()
891 || (SQUARE (x0
- Crosshair
.X
) +
892 SQUARE (y0
- Crosshair
.Y
) >
893 SQUARE (pin
->X
- Crosshair
.X
) + SQUARE (pin
->Y
- Crosshair
.Y
)))
899 else if (ans
& LINEPOINT_TYPE
)
901 PointTypePtr pnt
= (PointTypePtr
) ptr3
;
902 if (((x0
- Crosshair
.X
) * (x0
- Crosshair
.X
) +
903 (y0
- Crosshair
.Y
) * (y0
- Crosshair
.Y
)) >
904 ((pnt
->X
- Crosshair
.X
) * (pnt
->X
- Crosshair
.X
) +
905 (pnt
->Y
- Crosshair
.Y
) * (pnt
->Y
- Crosshair
.Y
)))
911 else if (ans
& ELEMENT_TYPE
)
913 ElementTypePtr el
= (ElementTypePtr
) ptr1
;
914 if (SQUARE (x0
- Crosshair
.X
) + SQUARE (y0
- Crosshair
.Y
) >
915 SQUARE (el
->MarkX
- Crosshair
.X
) + SQUARE (el
->MarkY
- Crosshair
.Y
))
921 if (x0
>= 0 && y0
>= 0)
926 if (Settings
.Mode
== ARROW_MODE
)
929 SearchScreen (Crosshair
.X
, Crosshair
.Y
, LINEPOINT_TYPE
,
930 &ptr1
, &ptr2
, &ptr3
);
932 hid_action("PointCursor");
933 else if (!TEST_FLAG(SELECTEDFLAG
, (LineType
*)ptr2
))
934 hid_actionl("PointCursor","True", NULL
);
936 if (Settings
.Mode
== LINE_MODE
937 && Crosshair
.AttachedLine
.State
!= STATE_FIRST
938 && TEST_FLAG (AUTODRCFLAG
, PCB
))
941 gui
->set_crosshair (Crosshair
.X
, Crosshair
.Y
, HID_SC_DO_NOTHING
);
944 /* ---------------------------------------------------------------------------
945 * move crosshair relative (has to be switched off)
948 MoveCrosshairRelative (LocationType DeltaX
, LocationType DeltaY
)
950 FitCrosshairIntoGrid (Crosshair
.X
+ DeltaX
, Crosshair
.Y
+ DeltaY
);
953 /* ---------------------------------------------------------------------------
954 * move crosshair absolute switched off if it moved
955 * return true if it switched off
958 MoveCrosshairAbsolute (LocationType X
, LocationType Y
)
960 LocationType x
, y
, z
;
963 FitCrosshairIntoGrid (X
, Y
);
964 if (Crosshair
.X
!= x
|| Crosshair
.Y
!= y
)
966 /* back up to old position and erase crosshair */
972 HideCrosshair (false);
973 /* now move forward again */
981 /* ---------------------------------------------------------------------------
982 * sets the valid range for the crosshair cursor
985 SetCrosshairRange (LocationType MinX
, LocationType MinY
, LocationType MaxX
,
988 Crosshair
.MinX
= MAX (0, MinX
);
989 Crosshair
.MinY
= MAX (0, MinY
);
990 Crosshair
.MaxX
= MIN ((LocationType
) PCB
->MaxWidth
, MaxX
);
991 Crosshair
.MaxY
= MIN ((LocationType
) PCB
->MaxHeight
, MaxY
);
993 /* force update of position */
994 MoveCrosshairRelative (0, 0);
997 /* --------------------------------------------------------------------------
998 * draw the marker position
999 * if argument is true, draw only if it is visible, otherwise draw it regardless
1002 DrawMark (bool ifvis
)
1004 if (Marked
.status
|| !ifvis
)
1006 gui
->draw_line (Crosshair
.GC
,
1007 Marked
.X
- MARK_SIZE
,
1008 Marked
.Y
- MARK_SIZE
,
1009 Marked
.X
+ MARK_SIZE
, Marked
.Y
+ MARK_SIZE
);
1010 gui
->draw_line (Crosshair
.GC
,
1011 Marked
.X
+ MARK_SIZE
,
1012 Marked
.Y
- MARK_SIZE
,
1013 Marked
.X
- MARK_SIZE
, Marked
.Y
+ MARK_SIZE
);
1017 /* ---------------------------------------------------------------------------
1018 * initializes crosshair stuff
1019 * clears the struct, allocates to graphical contexts and
1020 * initializes the stack
1023 InitCrosshair (void)
1025 Crosshair
.GC
= gui
->make_gc ();
1027 gui
->set_color (Crosshair
.GC
, Settings
.CrosshairColor
);
1028 gui
->set_draw_xor (Crosshair
.GC
, 1);
1029 gui
->set_line_cap (Crosshair
.GC
, Trace_Cap
);
1030 gui
->set_line_width (Crosshair
.GC
, 1);
1032 /* fake a crosshair off entry on stack */
1033 CrosshairStackLocation
= 0;
1034 CrosshairStack
[CrosshairStackLocation
++] = true;
1035 Crosshair
.On
= false;
1037 /* set initial shape */
1038 Crosshair
.shape
= Basic_Crosshair_Shape
;
1040 /* set default limits */
1041 Crosshair
.MinX
= Crosshair
.MinY
= 0;
1042 Crosshair
.MaxX
= PCB
->MaxWidth
;
1043 Crosshair
.MaxY
= PCB
->MaxHeight
;
1045 /* clear the mark */
1046 Marked
.status
= false;
1049 /* ---------------------------------------------------------------------------
1050 * exits crosshair routines, release GCs
1053 DestroyCrosshair (void)
1055 CrosshairOff (true);
1056 FreePolygonMemory (&Crosshair
.AttachedPolygon
);
1057 gui
->destroy_gc (Crosshair
.GC
);