Add support for filling / thindrawing raw polygons to the HID interface
[geda-pcb/gde.git] / src / hid / gtk / gtkhid-main.c
blob484cee06d2c13b263e6d77daa7f11847afb1141c
1 /* $Id$ */
3 #ifdef HAVE_CONFIG_H
4 #include "config.h"
5 #endif
7 #include <stdio.h>
8 #include <stdlib.h>
9 #ifdef HAVE_STRING_H
10 #include <string.h>
11 #endif
12 #include <math.h>
13 #include <time.h>
16 #include "global.h"
17 #include "action.h"
18 #include "crosshair.h"
19 #include "data.h"
20 #include "draw.h"
21 #include "error.h"
22 #include "mymem.h"
23 #include "draw.h"
24 #include "clip.h"
26 #include "hid.h"
27 #include "../hidint.h"
28 #include "gui.h"
29 #include "hid/common/draw_helpers.h"
32 #if !GTK_CHECK_VERSION(2,8,0) && defined(HAVE_GDK_GDKX_H)
33 #include <gdk/gdkx.h>
34 #endif
36 #ifdef HAVE_LIBDMALLOC
37 #include <dmalloc.h>
38 #endif
41 RCSID ("$Id$");
44 extern HID ghid_hid;
47 static void zoom_to (double factor, int x, int y);
48 static void zoom_by (double factor, int x, int y);
50 /* Sets gport->u_gc to the "right" GC to use (wrt mask or window)
52 #define USE_GC(gc) if (!use_gc(gc)) return
54 static int cur_mask = -1;
55 static int mask_seq = 0;
57 int ghid_flip_x = 0, ghid_flip_y = 0;
59 /* ------------------------------------------------------------ */
61 /* Px converts view->pcb, Vx converts pcb->view */
63 static inline int
64 Vx (int x)
66 int rv;
67 if (ghid_flip_x)
68 rv = (PCB->MaxWidth - x - gport->view_x0) / gport->zoom + 0.5;
69 else
70 rv = (x - gport->view_x0) / gport->zoom + 0.5;
71 return rv;
74 static inline int
75 Vx2 (int x)
77 return (x - gport->view_x0) / gport->zoom + 0.5;
80 static inline int
81 Vy (int y)
83 int rv;
84 if (ghid_flip_y)
85 rv = (PCB->MaxHeight - y - gport->view_y0) / gport->zoom + 0.5;
86 else
87 rv = (y - gport->view_y0) / gport->zoom + 0.5;
88 return rv;
91 static inline int
92 Vy2 (int y)
94 return (y - gport->view_y0) / gport->zoom + 0.5;
97 static inline int
98 Vz (int z)
100 return z / gport->zoom + 0.5;
103 static inline int
104 Px (int x)
106 int rv = x * gport->zoom + gport->view_x0;
107 if (ghid_flip_x)
108 rv = PCB->MaxWidth - (x * gport->zoom + gport->view_x0);
109 return rv;
112 static inline int
113 Py (int y)
115 int rv = y * gport->zoom + gport->view_y0;
116 if (ghid_flip_y)
117 rv = PCB->MaxHeight - (y * gport->zoom + gport->view_y0);
118 return rv;
121 static inline int
122 Pz (int z)
124 return (z * gport->zoom);
127 /* ------------------------------------------------------------ */
129 static void
130 ghid_pan_fixup ()
134 * don't pan so far to the right that we see way past the right
135 * edge of the board.
137 if (gport->view_x0 > PCB->MaxWidth - gport->view_width)
138 gport->view_x0 = PCB->MaxWidth - gport->view_width;
141 * don't pan so far down that we see way past the bottom edge of
142 * the board.
144 if (gport->view_y0 > PCB->MaxHeight - gport->view_height)
145 gport->view_y0 = PCB->MaxHeight - gport->view_height;
147 /* don't view above or to the left of the board... ever */
148 if (gport->view_x0 < 0)
149 gport->view_x0 = 0;
151 if (gport->view_y0 < 0)
152 gport->view_y0 = 0;
155 /* if we can see the entire board and some, then zoom to fit */
156 if (gport->view_width > PCB->MaxWidth &&
157 gport->view_height > PCB->MaxHeight)
159 zoom_by (1, 0, 0);
160 return;
163 gtk_range_set_value (GTK_RANGE (ghidgui->h_range), gport->view_x0);
164 gtk_range_set_value (GTK_RANGE (ghidgui->v_range), gport->view_y0);
166 ghid_invalidate_all ();
170 /* ------------------------------------------------------------ */
172 static const char zoom_syntax[] =
173 "Zoom()\n"
174 "Zoom(factor)";
177 static const char zoom_help[] =
178 "Various zoom factor changes.";
180 /* %start-doc actions Zoom
181 Changes the zoom (magnification) of the view of the board. If no
182 arguments are passed, the view is scaled such that the board just fits
183 inside the visible window (i.e. ``view all''). Otherwise,
184 @var{factor} specifies a change in zoom factor. It may be prefixed by
185 @code{+}, @code{-}, or @code{=} to change how the zoom factor is
186 modified. The @var{factor} is a floating point number, such as
187 @code{1.5} or @code{0.75}.
189 @table @code
191 @item +@var{factor}
192 Values greater than 1.0 cause the board to be drawn smaller; more of
193 the board will be visible. Values between 0.0 and 1.0 cause the board
194 to be drawn bigger; less of the board will be visible.
196 @item -@var{factor}
197 Values greater than 1.0 cause the board to be drawn bigger; less of
198 the board will be visible. Values between 0.0 and 1.0 cause the board
199 to be drawn smaller; more of the board will be visible.
201 @item =@var{factor}
203 The @var{factor} is an absolute zoom factor; the unit for this value
204 is "PCB units per screen pixel". Since PCB units are 0.01 mil, a
205 @var{factor} of 1000 means 10 mils (0.01 in) per pixel, or 100 DPI,
206 about the actual resolution of most screens - resulting in an "actual
207 size" board. Similarly, a @var{factor} of 100 gives you a 10x actual
208 size.
210 @end table
212 Note that zoom factors of zero are silently ignored.
216 %end-doc */
218 static int
219 Zoom (int argc, char **argv, int x, int y)
221 double factor;
222 const char *vp;
223 double v;
225 if (argc > 1)
226 AFAIL (zoom);
228 if (x == 0 && y == 0)
230 x = gport->view_width / 2;
231 y = gport->view_height / 2;
233 else
235 /* Px converts view->pcb, Vx converts pcb->view */
236 x = Vx (x);
237 y = Vy (y);
240 if (argc < 1)
242 zoom_to (1000000, 0, 0);
243 return 0;
246 vp = argv[0];
247 if (*vp == '+' || *vp == '-' || *vp == '=')
248 vp++;
249 v = strtod (vp, 0);
250 if (v <= 0)
251 return 1;
252 switch (argv[0][0])
254 case '-':
255 factor = 1 / v;
256 zoom_by (1 / v, x, y);
257 break;
258 default:
259 case '+':
260 factor = v;
261 zoom_by (v, x, y);
262 break;
263 case '=':
264 /* this needs to set the scale factor absolutely*/
265 factor = 1.0;
266 zoom_to (v, x, y);
267 break;
270 return 0;
274 static void
275 zoom_to (double new_zoom, int x, int y)
277 double max_zoom, xfrac, yfrac;
278 int cx, cy;
280 /* gport->zoom:
281 * zoom value is PCB units per screen pixel. Larger numbers mean zooming
282 * out - the largest value means you are looking at the whole board.
284 * PCB units per screen pixel
286 * gport->view_width and gport->view_height are in PCB coordinates
289 #ifdef DEBUG
290 printf ("\nzoom_to( %g, %d, %d)\n", new_zoom, x, y);
291 #endif
293 xfrac = (double) x / (double) gport->view_width;
294 yfrac = (double) y / (double) gport->view_height;
296 if (ghid_flip_x)
297 xfrac = 1-xfrac;
298 if (ghid_flip_y)
299 yfrac = 1-yfrac;
301 /* Find the zoom that would just make the entire board fit */
302 max_zoom = PCB->MaxWidth / gport->width;
303 if (max_zoom < PCB->MaxHeight / gport->height)
304 max_zoom = PCB->MaxHeight / gport->height;
306 #ifdef DEBUG
307 printf ("zoom_to(): max_zoom = %g\n", max_zoom);
308 #endif
311 * clip the zooming so we can never have more than 1 pixel per PCB
312 * unit and never zoom out more than viewing the entire board
315 if (new_zoom < 1)
316 new_zoom = 1;
317 if (new_zoom > max_zoom)
318 new_zoom = max_zoom;
320 #ifdef DEBUG
321 printf ("max_zoom = %g, xfrac = %g, yfrac = %g, new_zoom = %g\n",
322 max_zoom, xfrac, yfrac, new_zoom);
323 #endif
325 /* find center x and y */
326 cx = gport->view_x0 + gport->view_width * xfrac * gport->zoom;
327 cy = gport->view_y0 + gport->view_height * yfrac * gport->zoom;
329 #ifdef DEBUG
330 printf ("zoom_to(): x0 = %d, cx = %d\n", gport->view_x0, cx);
331 printf ("zoom_to(): y0 = %d, cy = %d\n", gport->view_y0, cy);
332 #endif
334 if (gport->zoom != new_zoom)
336 gdouble xtmp, ytmp;
337 gint x0, y0;
339 xtmp = (gport->view_x - gport->view_x0) / (gdouble) gport->view_width;
340 ytmp = (gport->view_y - gport->view_y0) / (gdouble) gport->view_height;
342 gport->zoom = new_zoom;
343 pixel_slop = new_zoom;
344 ghid_port_ranges_scale(FALSE);
346 x0 = gport->view_x - xtmp * gport->view_width;
347 if (x0 < 0)
348 x0 = 0;
349 gport->view_x0 = x0;
351 y0 = gport->view_y - ytmp * gport->view_height;
352 if (y0 < 0)
353 y0 = 0;
354 gport->view_y0 = y0;
356 ghidgui->adjustment_changed_holdoff = TRUE;
357 gtk_range_set_value (GTK_RANGE (ghidgui->h_range), gport->view_x0);
358 gtk_range_set_value (GTK_RANGE (ghidgui->v_range), gport->view_y0);
359 ghidgui->adjustment_changed_holdoff = FALSE;
361 ghid_port_ranges_changed();
364 #ifdef DEBUG
365 printf ("zoom_to(): new x0 = %d\n", gport->view_x0);
366 printf ("zoom_to(): new y0 = %d\n", gport->view_y0);
367 #endif
368 ghid_set_status_line_label ();
371 void
372 zoom_by (double factor, int x, int y)
374 #ifdef DEBUG
375 printf ("\nzoom_by( %g, %d, %d). old gport->zoom = %g\n",
376 factor, x, y, gport->zoom);
377 #endif
378 zoom_to (gport->zoom * factor, x, y);
381 /* ------------------------------------------------------------ */
383 static void
384 draw_grid ()
386 static GdkPoint *points = 0;
387 static int npoints = 0;
388 int x1, y1, x2, y2, n, i;
389 double x, y;
391 if (!Settings.DrawGrid)
392 return;
393 if (Vz (PCB->Grid) < MIN_GRID_DISTANCE)
394 return;
395 if (!gport->grid_gc)
397 if (gdk_color_parse (Settings.GridColor, &gport->grid_color))
399 gport->grid_color.red ^= gport->bg_color.red;
400 gport->grid_color.green ^= gport->bg_color.green;
401 gport->grid_color.blue ^= gport->bg_color.blue;
402 gdk_color_alloc (gport->colormap, &gport->grid_color);
404 gport->grid_gc = gdk_gc_new (gport->drawable);
405 gdk_gc_set_function (gport->grid_gc, GDK_XOR);
406 gdk_gc_set_foreground (gport->grid_gc, &gport->grid_color);
408 x1 = GRIDFIT_X (SIDE_X (gport->view_x0), PCB->Grid);
409 y1 = GRIDFIT_Y (SIDE_Y (gport->view_y0), PCB->Grid);
410 x2 = GRIDFIT_X (SIDE_X (gport->view_x0 + gport->view_width - 1), PCB->Grid);
411 y2 = GRIDFIT_Y (SIDE_Y (gport->view_y0 + gport->view_height - 1), PCB->Grid);
412 if (x1 > x2)
414 int tmp = x1;
415 x1 = x2;
416 x2 = tmp;
418 if (y1 > y2)
420 int tmp = y1;
421 y1 = y2;
422 y2 = tmp;
424 if (Vx (x1) < 0)
425 x1 += PCB->Grid;
426 if (Vy (y1) < 0)
427 y1 += PCB->Grid;
428 if (Vx (x2) >= gport->width)
429 x2 -= PCB->Grid;
430 if (Vy (y2) >= gport->height)
431 y2 -= PCB->Grid;
432 n = (int) ((x2 - x1) / PCB->Grid + 0.5) + 1;
433 if (n > npoints)
435 npoints = n + 10;
436 points =
437 MyRealloc (points, npoints * sizeof (GdkPoint), "gtk_draw_grid");
439 n = 0;
440 for (x = x1; x <= x2; x += PCB->Grid)
442 points[n].x = Vx (x);
443 n++;
445 for (y = y1; y <= y2; y += PCB->Grid)
447 int vy = Vy (y);
448 for (i = 0; i < n; i++)
449 points[i].y = vy;
450 gdk_draw_points (gport->drawable, gport->grid_gc, points, n);
454 /* ------------------------------------------------------------ */
456 HID_Attribute *
457 ghid_get_export_options (int *n_ret)
459 return NULL;
463 void
464 ghid_invalidate_wh (int x, int y, int width, int height, int last)
466 ghid_invalidate_all ();
469 void
470 ghid_invalidate_lr (int left, int right, int top, int bottom, int last)
472 ghid_invalidate_all ();
475 static void
476 ghid_draw_bg_image(void)
478 static GdkPixbuf *pixbuf;
479 GdkInterpType interp_type;
480 gint x, y, w, h, w_src, h_src;
481 static gint w_scaled, h_scaled;
483 if (!ghidgui->bg_pixbuf)
484 return;
486 w = PCB->MaxWidth / gport->zoom;
487 h = PCB->MaxHeight / gport->zoom;
488 x = gport->view_x0 / gport->zoom;
489 y = gport->view_y0 / gport->zoom;
491 if (w_scaled != w || h_scaled != h)
493 if (pixbuf)
494 g_object_unref(G_OBJECT(pixbuf));
496 w_src = gdk_pixbuf_get_width(ghidgui->bg_pixbuf);
497 h_src = gdk_pixbuf_get_height(ghidgui->bg_pixbuf);
498 if (w > w_src && h > h_src)
499 interp_type = GDK_INTERP_NEAREST;
500 else
501 interp_type = GDK_INTERP_BILINEAR;
503 pixbuf = gdk_pixbuf_scale_simple(ghidgui->bg_pixbuf, w, h, interp_type);
504 w_scaled = w;
505 h_scaled = h;
507 if (pixbuf)
508 gdk_pixbuf_render_to_drawable(pixbuf, gport->drawable, gport->bg_gc,
509 x, y, 0, 0,
510 w - x, h - y, GDK_RGB_DITHER_NORMAL, 0, 0);
513 void
514 ghid_invalidate_all ()
516 int eleft, eright, etop, ebottom;
517 BoxType region;
519 if (!gport->pixmap)
520 return;
522 region.X1 = MIN(Px(0), Px(gport->width + 1));
523 region.Y1 = MIN(Py(0), Py(gport->height + 1));
524 region.X2 = MAX(Px(0), Px(gport->width + 1));
525 region.Y2 = MAX(Py(0), Py(gport->height + 1));
527 eleft = Vx (0);
528 eright = Vx (PCB->MaxWidth);
529 etop = Vy (0);
530 ebottom = Vy (PCB->MaxHeight);
531 if (eleft > eright)
533 int tmp = eleft;
534 eleft = eright;
535 eright = tmp;
537 if (etop > ebottom)
539 int tmp = etop;
540 etop = ebottom;
541 ebottom = tmp;
544 if (eleft > 0)
545 gdk_draw_rectangle (gport->drawable, gport->offlimits_gc,
546 1, 0, 0, eleft, gport->height);
547 else
548 eleft = 0;
549 if (eright < gport->width)
550 gdk_draw_rectangle (gport->drawable, gport->offlimits_gc,
551 1, eright, 0, gport->width - eright, gport->height);
552 else
553 eright = gport->width;
554 if (etop > 0)
555 gdk_draw_rectangle (gport->drawable, gport->offlimits_gc,
556 1, eleft, 0, eright - eleft + 1, etop);
557 else
558 etop = 0;
559 if (ebottom < gport->height)
560 gdk_draw_rectangle (gport->drawable, gport->offlimits_gc,
561 1, eleft, ebottom, eright - eleft + 1,
562 gport->height - ebottom);
563 else
564 ebottom = gport->height;
566 gdk_draw_rectangle (gport->drawable, gport->bg_gc, 1,
567 eleft, etop, eright - eleft + 1, ebottom - etop + 1);
569 ghid_draw_bg_image();
571 hid_expose_callback (&ghid_hid, &region, 0);
572 draw_grid ();
573 if (ghidgui->need_restore_crosshair)
574 RestoreCrosshair (FALSE);
575 ghidgui->need_restore_crosshair = FALSE;
576 ghid_screen_update ();
581 ghid_set_layer (const char *name, int group, int empty)
583 int idx = (group >= 0
584 && group <
585 max_layer) ? PCB->LayerGroups.Entries[group][0] : group;
587 if (idx >= 0 && idx < max_layer + 2)
588 return /*pinout ? 1 : */ PCB->Data->Layer[idx].On;
589 if (idx < 0)
591 switch (SL_TYPE (idx))
593 case SL_INVISIBLE:
594 return /* pinout ? 0 : */ PCB->InvisibleObjectsOn;
595 case SL_MASK:
596 if (SL_MYSIDE (idx) /*&& !pinout */ )
597 return TEST_FLAG (SHOWMASKFLAG, PCB);
598 return 0;
599 case SL_SILK:
600 if (SL_MYSIDE (idx) /*|| pinout */ )
601 return PCB->ElementOn;
602 return 0;
603 case SL_ASSY:
604 return 0;
605 case SL_PDRILL:
606 case SL_UDRILL:
607 return 1;
610 return 0;
613 #define WHICH_GC(gc) (cur_mask == HID_MASK_CLEAR ? gport->mask_gc : (gc)->gc)
615 void
616 ghid_use_mask (int use_it)
618 static int mask_seq_id = 0;
619 GdkColor color;
621 if (!gport->pixmap)
622 return;
623 if (use_it == cur_mask)
624 return;
625 switch (use_it)
627 case HID_MASK_OFF:
628 gport->drawable = gport->pixmap;
629 mask_seq = 0;
630 break;
632 case HID_MASK_BEFORE:
633 printf ("gtk doesn't support mask_before!\n");
634 abort ();
636 case HID_MASK_CLEAR:
637 if (!gport->mask)
638 gport->mask = gdk_pixmap_new (0, gport->width, gport->height, 1);
639 gport->drawable = gport->mask;
640 mask_seq = 0;
641 if (!gport->mask_gc)
643 gport->mask_gc = gdk_gc_new (gport->drawable);
645 color.pixel = 1;
646 gdk_gc_set_foreground (gport->mask_gc, &color);
647 gdk_draw_rectangle (gport->drawable, gport->mask_gc, TRUE, 0, 0,
648 gport->width, gport->height);
649 color.pixel = 0;
650 gdk_gc_set_foreground (gport->mask_gc, &color);
651 break;
653 case HID_MASK_AFTER:
654 mask_seq_id++;
655 if (!mask_seq_id)
656 mask_seq_id = 1;
657 mask_seq = mask_seq_id;
659 gport->drawable = gport->pixmap;
660 break;
663 cur_mask = use_it;
666 void
667 ghid_extents_use_mask (int use_it)
672 typedef struct
674 int color_set;
675 GdkColor color;
676 int xor_set;
677 GdkColor xor_color;
678 } ColorCache;
681 /* Config helper functions for when the user changes color preferences.
682 | set_special colors used in the gtkhid.
684 static void
685 set_special_grid_color (void)
687 if (!gport->colormap)
688 return;
689 gport->grid_color.red ^= gport->bg_color.red;
690 gport->grid_color.green ^= gport->bg_color.green;
691 gport->grid_color.blue ^= gport->bg_color.blue;
692 gdk_color_alloc (gport->colormap, &gport->grid_color);
693 if (gport->grid_gc)
694 gdk_gc_set_foreground (gport->grid_gc, &gport->grid_color);
697 void
698 ghid_set_special_colors (HID_Attribute * ha)
700 if (!ha->name || !ha->value)
701 return;
702 if (!strcmp (ha->name, "background-color") && gport->bg_gc)
704 ghid_map_color_string (*(char **) ha->value, &gport->bg_color);
705 gdk_gc_set_foreground (gport->bg_gc, &gport->bg_color);
706 set_special_grid_color ();
708 else if (!strcmp (ha->name, "off-limit-color") && gport->offlimits_gc)
710 ghid_map_color_string (*(char **) ha->value, &gport->offlimits_color);
711 gdk_gc_set_foreground (gport->offlimits_gc, &gport->offlimits_color);
713 else if (!strcmp (ha->name, "grid-color") && gport->grid_gc)
715 ghid_map_color_string (*(char **) ha->value, &gport->grid_color);
716 set_special_grid_color ();
720 void
721 ghid_set_color (hidGC gc, const char *name)
723 static void *cache = 0;
724 hidval cval;
726 if (name == NULL)
728 fprintf (stderr, "%s(): name = NULL, setting to magenta\n",
729 __FUNCTION__);
730 name = "magenta";
733 gc->colorname = (char *) name;
734 if (!gc->gc)
735 return;
736 if (gport->colormap == 0)
737 gport->colormap = gtk_widget_get_colormap (gport->top_window);
739 if (strcmp (name, "erase") == 0)
741 gdk_gc_set_foreground (gc->gc, &gport->bg_color);
742 gc->erase = 1;
744 else if (strcmp (name, "drill") == 0)
746 gdk_gc_set_foreground (gc->gc, &gport->offlimits_color);
747 gc->erase = 0;
749 else
751 ColorCache *cc;
752 if (hid_cache_color (0, name, &cval, &cache))
753 cc = (ColorCache *) cval.ptr;
754 else
756 cc = (ColorCache *) malloc (sizeof (ColorCache));
757 memset (cc, 0, sizeof (*cc));
758 cval.ptr = cc;
759 hid_cache_color (1, name, &cval, &cache);
762 if (!cc->color_set)
764 if (gdk_color_parse (name, &cc->color))
765 gdk_color_alloc (gport->colormap, &cc->color);
766 else
767 gdk_color_white (gport->colormap, &cc->color);
768 cc->color_set = 1;
770 if (gc->xor)
772 if (!cc->xor_set)
774 cc->xor_color.red = cc->color.red ^ gport->bg_color.red;
775 cc->xor_color.green = cc->color.green ^ gport->bg_color.green;
776 cc->xor_color.blue = cc->color.blue ^ gport->bg_color.blue;
777 gdk_color_alloc (gport->colormap, &cc->xor_color);
778 cc->xor_set = 1;
780 gdk_gc_set_foreground (gc->gc, &cc->xor_color);
782 else
784 gdk_gc_set_foreground (gc->gc, &cc->color);
787 gc->erase = 0;
791 void
792 ghid_set_line_cap (hidGC gc, EndCapStyle style)
795 switch (style)
797 case Trace_Cap:
798 case Round_Cap:
799 gc->cap = GDK_CAP_ROUND;
800 gc->join = GDK_JOIN_ROUND;
801 break;
802 case Square_Cap:
803 case Beveled_Cap:
804 gc->cap = GDK_CAP_PROJECTING;
805 gc->join = GDK_JOIN_MITER;
806 break;
808 if (gc->gc)
809 gdk_gc_set_line_attributes (WHICH_GC (gc),
810 Vz (gc->width), GDK_LINE_SOLID,
811 gc->cap, gc->join);
814 void
815 ghid_set_line_width (hidGC gc, int width)
818 gc->width = width;
819 if (gc->gc)
820 gdk_gc_set_line_attributes (WHICH_GC (gc),
821 Vz (gc->width), GDK_LINE_SOLID,
822 gc->cap, gc->join);
825 void
826 ghid_set_draw_xor (hidGC gc, int xor)
828 gc->xor = xor;
829 if (!gc->gc)
830 return;
831 gdk_gc_set_function (gc->gc, xor ? GDK_XOR : GDK_COPY);
832 ghid_set_color (gc, gc->colorname);
835 void
836 ghid_set_draw_faded (hidGC gc, int faded)
838 printf ("ghid_set_draw_faded(%p,%d) -- not implemented\n", gc, faded);
841 void
842 ghid_set_line_cap_angle (hidGC gc, int x1, int y1, int x2, int y2)
844 printf ("ghid_set_line_cap_angle() -- not implemented\n");
847 static int
848 use_gc (hidGC gc)
850 if (!gport->pixmap)
851 return 0;
852 if (!gc->gc)
854 gc->gc = gdk_gc_new (gport->top_window->window);
855 ghid_set_color (gc, gc->colorname);
856 ghid_set_line_width (gc, gc->width);
857 ghid_set_line_cap (gc, gc->cap);
858 ghid_set_draw_xor (gc, gc->xor);
860 if (gc->mask_seq != mask_seq)
862 if (mask_seq)
863 gdk_gc_set_clip_mask (gc->gc, gport->mask);
864 else
865 gdk_gc_set_clip_mask (gc->gc, NULL);
866 gc->mask_seq = mask_seq;
868 gport->u_gc = WHICH_GC (gc);
869 return 1;
872 void
873 ghid_draw_line (hidGC gc, int x1, int y1, int x2, int y2)
875 double dx1, dy1, dx2, dy2;
877 dx1 = Vx ((double)x1);
878 dy1 = Vy ((double)y1);
879 dx2 = Vx ((double)x2);
880 dy2 = Vy ((double)y2);
882 if (! ClipLine (0, 0, gport->width, gport->height,
883 &dx1, &dy1, &dx2, &dy2, gc->width / gport->zoom))
884 return;
886 USE_GC (gc);
887 gdk_draw_line (gport->drawable, gport->u_gc, dx1, dy1, dx2, dy2);
890 void
891 ghid_draw_arc (hidGC gc, int cx, int cy,
892 int xradius, int yradius, int start_angle, int delta_angle)
894 gint vrx, vry;
895 gint w, h, radius;
897 w = gport->width * gport->zoom;
898 h = gport->height * gport->zoom;
899 radius = (xradius > yradius) ? xradius : yradius;
900 if (SIDE_X (cx) < gport->view_x0 - radius
901 || SIDE_X (cx) > gport->view_x0 + w + radius
902 || SIDE_Y (cy) < gport->view_y0 - radius
903 || SIDE_Y (cy) > gport->view_y0 + h + radius)
904 return;
906 USE_GC (gc);
907 vrx = Vz (xradius);
908 vry = Vz (yradius);
910 if (ghid_flip_x)
912 start_angle = 180 - start_angle;
913 delta_angle = - delta_angle;
915 if (ghid_flip_y)
917 start_angle = - start_angle;
918 delta_angle = - delta_angle;
920 /* make sure we fall in the -180 to +180 range */
921 start_angle = (start_angle + 360 + 180) % 360 - 180;
923 gdk_draw_arc (gport->drawable, gport->u_gc, 0,
924 Vx (cx) - vrx, Vy (cy) - vry,
925 vrx * 2, vry * 2, (start_angle + 180) * 64, delta_angle * 64);
928 void
929 ghid_draw_rect (hidGC gc, int x1, int y1, int x2, int y2)
931 gint w, h, lw;
933 lw = gc->width;
934 w = gport->width * gport->zoom;
935 h = gport->height * gport->zoom;
937 if ((SIDE_X (x1) < gport->view_x0 - lw
938 && SIDE_X (x2) < gport->view_x0 - lw)
939 || (SIDE_X (x1) > gport->view_x0 + w + lw
940 && SIDE_X (x2) > gport->view_x0 + w + lw)
941 || (SIDE_Y (y1) < gport->view_y0 - lw
942 && SIDE_Y (y2) < gport->view_y0 - lw)
943 || (SIDE_Y (y1) > gport->view_y0 + h + lw
944 && SIDE_Y (y2) > gport->view_y0 + h + lw))
945 return;
947 x1 = Vx (x1);
948 y1 = Vy (y1);
949 x2 = Vx (x2);
950 y2 = Vy (y2);
952 if (x1 > x2) { gint xt = x1; x1 = x2; x2 = xt; }
953 if (y1 > y2) { gint yt = y1; y1 = y2; y2 = yt; }
955 USE_GC (gc);
956 gdk_draw_rectangle (gport->drawable, gport->u_gc, FALSE,
957 x1, y1, x2 - x1 + 1, y2 - y1 + 1);
961 void
962 ghid_fill_circle (hidGC gc, int cx, int cy, int radius)
964 gint w, h, vr;
966 w = gport->width * gport->zoom;
967 h = gport->height * gport->zoom;
968 if (SIDE_X (cx) < gport->view_x0 - radius
969 || SIDE_X (cx) > gport->view_x0 + w + radius
970 || SIDE_Y (cy) < gport->view_y0 - radius
971 || SIDE_Y (cy) > gport->view_y0 + h + radius)
972 return;
974 USE_GC (gc);
975 vr = Vz (radius);
976 gdk_draw_arc (gport->drawable, gport->u_gc, TRUE,
977 Vx (cx) - vr, Vy (cy) - vr,
978 vr * 2, vr * 2, 0, 360 * 64);
981 void
982 ghid_fill_polygon (hidGC gc, int n_coords, int *x, int *y)
984 static GdkPoint *points = 0;
985 static int npoints = 0;
986 int i;
987 USE_GC (gc);
989 if (npoints < n_coords)
991 npoints = n_coords + 1;
992 points = MyRealloc (points,
993 npoints * sizeof (GdkPoint), (char *) __FUNCTION__);
995 for (i = 0; i < n_coords; i++)
997 points[i].x = Vx (x[i]);
998 points[i].y = Vy (y[i]);
1000 gdk_draw_polygon (gport->drawable, gport->u_gc, 1, points, n_coords);
1003 void
1004 ghid_fill_rect (hidGC gc, int x1, int y1, int x2, int y2)
1006 gint w, h, lw, xx, yy;
1008 lw = gc->width;
1009 w = gport->width * gport->zoom;
1010 h = gport->height * gport->zoom;
1012 if ((SIDE_X (x1) < gport->view_x0 - lw
1013 && SIDE_X (x2) < gport->view_x0 - lw)
1014 || (SIDE_X (x1) > gport->view_x0 + w + lw
1015 && SIDE_X (x2) > gport->view_x0 + w + lw)
1016 || (SIDE_Y (y1) < gport->view_y0 - lw
1017 && SIDE_Y (y2) < gport->view_y0 - lw)
1018 || (SIDE_Y (y1) > gport->view_y0 + h + lw
1019 && SIDE_Y (y2) > gport->view_y0 + h + lw))
1020 return;
1022 x1 = Vx (x1);
1023 y1 = Vy (y1);
1024 x2 = Vx (x2);
1025 y2 = Vy (y2);
1026 if (x2 < x1)
1028 xx = x1;
1029 x1 = x2;
1030 x2 = xx;
1032 if (y2 < y1)
1034 yy = y1;
1035 y1 = y2;
1036 y2 = yy;
1038 USE_GC (gc);
1039 gdk_draw_rectangle (gport->drawable, gport->u_gc, TRUE,
1040 x1, y1, x2 - x1 + 1, y2 - y1 + 1);
1043 void
1044 ghid_extents_draw_line (hidGC gc, int x1, int y1, int x2, int y2)
1046 printf ("ghid_extents_draw_line() -- not implemented\n");
1049 void
1050 ghid_extents_draw_arc (hidGC gc, int cx, int cy,
1051 int xradius, int yradius,
1052 int start_angle, int delta_angle)
1054 printf ("ghid_extents_draw_arc() -- not implemented\n");
1057 void
1058 ghid_extents_draw_rect (hidGC gc, int x1, int y1, int x2, int y2)
1060 printf ("ghid_extents_draw_rect() -- not implemented\n");
1063 void
1064 ghid_extents_fill_circle (hidGC gc, int cx, int cy, int radius)
1066 printf ("ghid_extents_fill_circle() -- not implemented\n");
1069 void
1070 ghid_extents_fill_polygon (hidGC gc, int n_coords, int *x, int *y)
1072 printf ("ghid_extents_fill_polygon() -- not implemented\n");
1075 void
1076 ghid_extents_fill_rect (hidGC gc, int x1, int y1, int x2, int y2)
1078 printf ("ghid_extents_fill_rect() -- not implemented\n");
1081 void
1082 ghid_calibrate (double xval, double yval)
1084 printf ("ghid_calibrate() -- not implemented\n");
1087 static int ghid_gui_is_up = 0;
1089 void
1090 ghid_notify_gui_is_up ()
1092 ghid_gui_is_up = 1;
1096 ghid_shift_is_pressed ()
1098 GdkModifierType mask;
1099 GHidPort *out = &ghid_port;
1101 if( ! ghid_gui_is_up )
1102 return 0;
1104 gdk_window_get_pointer (out->drawing_area->window, NULL, NULL, &mask);
1105 return (mask & GDK_SHIFT_MASK) ? TRUE : FALSE;
1109 ghid_control_is_pressed ()
1111 GdkModifierType mask;
1112 GHidPort *out = &ghid_port;
1114 if( ! ghid_gui_is_up )
1115 return 0;
1117 gdk_window_get_pointer (out->drawing_area->window, NULL, NULL, &mask);
1118 return (mask & GDK_CONTROL_MASK) ? TRUE : FALSE;
1121 void
1122 ghid_set_crosshair (int x, int y, int action)
1124 if (gport->x_crosshair != x || gport->y_crosshair != y)
1126 ghid_set_cursor_position_labels ();
1127 gport->x_crosshair = x;
1128 gport->y_crosshair = y;
1131 * FIXME - does this trigger the idle_proc stuff? It is in the
1132 * lesstif HID. Maybe something is needed here?
1134 * need_idle_proc ();
1140 * Pan the viewport so that the crosshair (which is in a fixed
1141 * location relative to the board) lands where the pointer
1142 * is. What happens is the crosshair is moved on the board
1143 * (see above) and then we move the board here to line it up
1144 * again. We do this by figuring out where the pointer is
1145 * in board coordinates and we know where the crosshair is
1146 * in board coordinates. Then we know how far to pan.
1148 if (action == HID_SC_PAN_VIEWPORT)
1150 GdkDisplay *display;
1151 GdkScreen *screen;
1152 gint pos_x, pos_y, xofs, yofs;
1154 display = gdk_display_get_default ();
1155 screen = gdk_display_get_default_screen (display);
1157 /* figure out where the pointer is relative to the display */
1158 gdk_display_get_pointer (display, NULL, &pos_x, &pos_y, NULL);
1161 * Figure out where the drawing area is on the screen so we can
1162 * figure out where the pointer is relative to the viewport.
1164 gdk_window_get_origin (gport->drawing_area->window, &xofs, &yofs);
1166 pos_x -= xofs;
1167 pos_y -= yofs;
1170 * pointer is at
1171 * px = gport->view_x0 + pos_x * gport->zoom
1172 * py = gport->view_y0 + pos_y * gport->zoom
1174 * cross hair is at
1178 * we need to shift x0 by (x - px) and y0 by (y - py)
1179 * x0 = x0 + x - (x0 + pos_x * zoom)
1180 * = x - pos_x*zoom
1183 if (ghid_flip_x)
1184 gport->view_x0 = x - (gport->view_width - pos_x * gport->zoom);
1185 else
1186 gport->view_x0 = x - pos_x * gport->zoom;
1188 if (ghid_flip_y)
1189 gport->view_y0 = y - (gport->view_height - pos_y * gport->zoom);
1190 else
1191 gport->view_y0 = y - pos_y * gport->zoom;
1193 ghid_pan_fixup();
1195 action = HID_SC_WARP_POINTER;
1198 if (action == HID_SC_WARP_POINTER)
1200 #if GTK_CHECK_VERSION(2,8,0)
1201 gint xofs, yofs;
1202 GdkDisplay *display;
1203 GdkScreen *screen;
1205 display = gdk_display_get_default ();
1206 screen = gdk_display_get_default_screen (display);
1209 * Figure out where the drawing area is on the screen because
1210 * gdk_display_warp_pointer will warp relative to the whole display
1211 * but the value we've been given is relative to your drawing area
1213 gdk_window_get_origin (gport->drawing_area->window, &xofs, &yofs);
1216 * Note that under X11, gdk_display_warp_pointer is just a wrapper around XWarpPointer, but
1217 * hopefully by avoiding the direct call to an X function we might still work under windows
1218 * and other non-X11 based gdk's
1220 gdk_display_warp_pointer (display, screen, xofs + Vx2 (x), yofs + Vy2 (y));
1223 #else
1224 # ifdef HAVE_GDK_GDKX_H
1225 gint xofs, yofs;
1226 gdk_window_get_origin (gport->drawing_area->window, &xofs, &yofs);
1227 XWarpPointer (GDK_DRAWABLE_XDISPLAY (gport->drawing_area->window),
1228 None, GDK_WINDOW_XID (gport->drawing_area->window),
1229 0, 0, 0, 0,
1230 xofs + Vx2 (x), yofs + Vy2 (y));
1231 # else
1232 # error "sorry. You need gtk+>=2.8.0 unless you are on X windows"
1233 # endif
1234 #endif
1238 typedef struct
1240 void (*func) ();
1241 gint id;
1242 hidval user_data;
1244 GuiTimer;
1246 /* We need a wrapper around the hid timer because a gtk timer needs
1247 | to return FALSE else the timer will be restarted.
1249 static gboolean
1250 ghid_timer (GuiTimer * timer)
1252 (*timer->func) (timer->user_data);
1253 ghid_mode_cursor (Settings.Mode);
1254 return FALSE; /* Turns timer off */
1257 hidval
1258 ghid_add_timer (void (*func) (hidval user_data),
1259 unsigned long milliseconds, hidval user_data)
1261 GuiTimer *timer = g_new0 (GuiTimer, 1);
1262 hidval ret;
1264 timer->func = func;
1265 timer->user_data = user_data;
1266 timer->id = gtk_timeout_add (milliseconds, (GtkFunction) ghid_timer, timer);
1267 ret.ptr = (void *) timer;
1268 return ret;
1271 void
1272 ghid_stop_timer (hidval timer)
1274 void *ptr = timer.ptr;
1276 gtk_timeout_remove (((GuiTimer *) ptr)->id);
1277 g_free( ptr );
1280 typedef struct
1282 void (*func) ( hidval, int, unsigned int, hidval );
1283 hidval user_data;
1284 int fd;
1285 GIOChannel *channel;
1286 gint id;
1288 GuiWatch;
1290 /* We need a wrapper around the hid file watch to pass the correct flags
1292 static gboolean
1293 ghid_watch (GIOChannel *source, GIOCondition condition, gpointer data)
1295 unsigned int pcb_condition = 0;
1296 hidval x;
1297 GuiWatch *watch = (GuiWatch*)data;
1299 if (condition & G_IO_IN)
1300 pcb_condition |= PCB_WATCH_READABLE;
1301 if (condition & G_IO_OUT)
1302 pcb_condition |= PCB_WATCH_WRITABLE;
1303 if (condition & G_IO_ERR)
1304 pcb_condition |= PCB_WATCH_ERROR;
1305 if (condition & G_IO_HUP)
1306 pcb_condition |= PCB_WATCH_HANGUP;
1308 x.ptr = (void *) watch;
1309 watch->func (x, watch->fd, pcb_condition, watch->user_data);
1310 ghid_mode_cursor (Settings.Mode);
1312 return TRUE; /* Leave watch on */
1315 hidval
1316 ghid_watch_file (int fd, unsigned int condition, void (*func) (hidval watch, int fd, unsigned int condition, hidval user_data),
1317 hidval user_data)
1319 GuiWatch *watch = g_new0 (GuiWatch, 1);
1320 hidval ret;
1321 unsigned int glib_condition = 0;
1323 if (condition & PCB_WATCH_READABLE)
1324 glib_condition |= G_IO_IN;
1325 if (condition & PCB_WATCH_WRITABLE)
1326 glib_condition |= G_IO_OUT;
1327 if (condition & PCB_WATCH_ERROR)
1328 glib_condition |= G_IO_ERR;
1329 if (condition & PCB_WATCH_HANGUP)
1330 glib_condition |= G_IO_HUP;
1332 watch->func = func;
1333 watch->user_data = user_data;
1334 watch->fd = fd;
1335 watch->channel = g_io_channel_unix_new( fd );
1336 watch->id = g_io_add_watch( watch->channel, glib_condition, ghid_watch, watch );
1338 ret.ptr = (void *) watch;
1339 return ret;
1342 void
1343 ghid_unwatch_file (hidval data)
1345 GuiWatch *watch = (GuiWatch*)data.ptr;
1347 g_io_channel_shutdown( watch->channel, TRUE, NULL );
1348 g_io_channel_unref( watch->channel );
1349 g_free( watch );
1352 typedef struct
1354 GSource source;
1355 void (*func) (hidval user_data);
1356 hidval user_data;
1357 } BlockHookSource;
1359 static gboolean ghid_block_hook_prepare (GSource *source,
1360 gint *timeout);
1361 static gboolean ghid_block_hook_check (GSource *source);
1362 static gboolean ghid_block_hook_dispatch (GSource *source,
1363 GSourceFunc callback,
1364 gpointer user_data);
1366 static GSourceFuncs ghid_block_hook_funcs = {
1367 ghid_block_hook_prepare,
1368 ghid_block_hook_check,
1369 ghid_block_hook_dispatch,
1370 NULL // No destroy notification
1373 static gboolean
1374 ghid_block_hook_prepare (GSource *source,
1375 gint *timeout)
1377 hidval data = ((BlockHookSource *)source)->user_data;
1378 ((BlockHookSource *)source)->func( data );
1379 return FALSE;
1382 static gboolean
1383 ghid_block_hook_check (GSource *source)
1385 return FALSE;
1388 static gboolean
1389 ghid_block_hook_dispatch (GSource *source,
1390 GSourceFunc callback,
1391 gpointer user_data)
1393 return FALSE;
1396 static hidval
1397 ghid_add_block_hook (void (*func) (hidval data),
1398 hidval user_data)
1400 hidval ret;
1401 BlockHookSource *source;
1403 source = (BlockHookSource *)g_source_new (&ghid_block_hook_funcs, sizeof( BlockHookSource ));
1405 source->func = func;
1406 source->user_data = user_data;
1408 g_source_attach ((GSource *)source, NULL);
1410 ret.ptr = (void *) source;
1411 return ret;
1414 static void
1415 ghid_stop_block_hook (hidval mlpoll)
1417 GSource *source = (GSource *)mlpoll.ptr;
1418 g_source_destroy( source );
1422 ghid_confirm_dialog (char *msg, ...)
1424 int rv;
1425 va_list ap;
1426 char *cancelmsg = NULL, *okmsg = NULL;
1428 va_start (ap, msg);
1429 cancelmsg = va_arg (ap, char *);
1430 okmsg = va_arg (ap, char *);
1431 va_end (ap);
1433 if (!cancelmsg)
1435 cancelmsg = _("_Cancel");
1436 okmsg = _("_OK");
1438 if (!okmsg)
1440 okmsg = _("_OK");
1443 rv = ghid_dialog_confirm (msg, cancelmsg, okmsg);
1445 return rv;
1449 ghid_close_confirm_dialog ()
1451 switch (ghid_dialog_close_confirm ())
1453 case GUI_DIALOG_CLOSE_CONFIRM_SAVE:
1455 if (hid_actionl ("Save", NULL))
1456 { /* Save failed */
1457 return 0; /* Cancel */
1458 } else {
1459 return 1; /* Close */
1462 case GUI_DIALOG_CLOSE_CONFIRM_NOSAVE:
1464 return 1; /* Close */
1466 case GUI_DIALOG_CLOSE_CONFIRM_CANCEL:
1467 default:
1469 return 0; /* Cancel */
1474 void
1475 ghid_report_dialog (char *title, char *msg)
1477 ghid_dialog_report (title, msg);
1480 char *
1481 ghid_prompt_for (char *msg, char *default_string)
1483 char *rv;
1485 rv = ghid_dialog_input (msg, default_string);
1486 return rv;
1489 /* FIXME -- implement a proper file select dialog */
1490 #ifdef FIXME
1491 char *
1492 ghid_fileselect (const char *title, const char *descr,
1493 char *default_file, char *default_ext,
1494 const char *history_tag, int flags)
1496 char *rv;
1498 rv = ghid_dialog_input (title, default_file);
1499 return rv;
1501 #endif
1503 void
1504 ghid_show_item (void *item)
1506 ghid_pinout_window_show (&ghid_port, (ElementTypePtr) item);
1509 void
1510 ghid_beep ()
1512 gdk_beep ();
1515 static int
1516 ghid_progress (int so_far, int total, const char *message)
1518 return 0;
1521 /* ---------------------------------------------------------------------- */
1523 HID ghid_hid = {
1524 sizeof (HID),
1525 "gtk",
1526 "Gtk - The Gimp Toolkit",
1527 1, /* gui */
1528 0, /* printer */
1529 0, /* exporter */
1530 0, /* poly before */
1531 1, /* poly after */
1532 0, /* poly dicer */
1534 ghid_get_export_options,
1535 ghid_do_export,
1536 ghid_parse_arguments,
1538 ghid_invalidate_wh,
1539 ghid_invalidate_lr,
1540 ghid_invalidate_all,
1541 ghid_set_layer,
1542 ghid_make_gc,
1543 ghid_destroy_gc,
1544 ghid_use_mask,
1545 ghid_set_color,
1546 ghid_set_line_cap,
1547 ghid_set_line_width,
1548 ghid_set_draw_xor,
1549 ghid_set_draw_faded,
1550 ghid_set_line_cap_angle,
1551 ghid_draw_line,
1552 ghid_draw_arc,
1553 ghid_draw_rect,
1554 ghid_fill_circle,
1555 ghid_fill_polygon,
1556 common_fill_pcb_polygon,
1557 common_thindraw_pcb_polygon,
1558 ghid_fill_rect,
1560 ghid_calibrate,
1561 ghid_shift_is_pressed,
1562 ghid_control_is_pressed,
1563 ghid_get_coords,
1564 ghid_set_crosshair,
1565 ghid_add_timer,
1566 ghid_stop_timer,
1567 ghid_watch_file,
1568 ghid_unwatch_file,
1569 ghid_add_block_hook,
1570 ghid_stop_block_hook,
1572 ghid_log,
1573 ghid_logv,
1574 ghid_confirm_dialog,
1575 ghid_close_confirm_dialog,
1576 ghid_report_dialog,
1577 ghid_prompt_for,
1578 ghid_fileselect,
1579 ghid_attribute_dialog,
1580 ghid_show_item,
1581 ghid_beep,
1582 ghid_progress
1585 HID ghid_extents = {
1586 sizeof (HID),
1587 "ghid_extents",
1588 "used to calculate extents",
1589 1, /* gui */
1590 0, /* printer */
1591 0, /* exporter */
1592 0, /* poly before */
1593 1, /* poly after */
1594 0, /* poly dicer */
1596 0 /* ghid_get_export_options */ ,
1597 0 /* ghid_do_export */ ,
1598 0 /* ghid_parse_arguments */ ,
1600 0 /* ghid_invalidate_wh */ ,
1601 0 /* ghid_invalidate_lr */ ,
1602 0 /* ghid_invalidate_all */ ,
1603 0 /* ghid_set_layer */ ,
1604 0 /* ghid_make_gc */ ,
1605 0 /* ghid_destroy_gc */ ,
1606 ghid_extents_use_mask,
1607 0 /* ghid_set_color */ ,
1608 0 /* ghid_set_line_cap */ ,
1609 0 /* ghid_set_line_width */ ,
1610 0 /* ghid_set_draw_xor */ ,
1611 0 /* ghid_set_draw_faded */ ,
1612 0 /* ghid_set_line_cap_angle */ ,
1613 ghid_extents_draw_line,
1614 ghid_extents_draw_arc,
1615 ghid_extents_draw_rect,
1616 ghid_extents_fill_circle,
1617 ghid_extents_fill_polygon,
1618 common_fill_pcb_polygon,
1619 0 /* ghid_extents_thindraw_pcb_polygon */ ,
1620 ghid_extents_fill_rect,
1622 0 /* ghid_calibrate */ ,
1623 0 /* ghid_shift_is_pressed */ ,
1624 0 /* ghid_control_is_pressed */ ,
1625 0 /* ghid_get_coords */ ,
1626 0 /* ghid_set_crosshair */ ,
1627 0 /* ghid_add_timer */ ,
1628 0 /* ghid_stop_timer */ ,
1629 0 /* ghid_watch_file */ ,
1630 0 /* ghid_unwatch_file */ ,
1631 0 /* ghid_add_block_hook */ ,
1632 0 /* ghid_stop_block_hook */ ,
1634 0 /* ghid_log */ ,
1635 0 /* ghid_logv */ ,
1636 0 /* ghid_confirm_dialog */ ,
1637 0 /* ghid_close_confirm_dialog */ ,
1638 0 /* ghid_report_dialog */ ,
1639 0 /* ghid_prompt_for */ ,
1640 0 /* ghid_attribute_dialog */ ,
1641 0 /* ghid_show_item */ ,
1642 0 /* ghid_beep */ ,
1643 0 /* ghid_progress */
1646 /* ------------------------------------------------------------
1648 * Actions specific to the GTK HID follow from here
1653 /* ------------------------------------------------------------ */
1654 static const char about_syntax[] =
1655 "About()";
1657 static const char about_help[] =
1658 "Tell the user about this version of PCB.";
1660 /* %start-doc actions About
1662 This just pops up a dialog telling the user which version of
1663 @code{pcb} they're running.
1665 %end-doc */
1668 static int
1669 About (int argc, char **argv, int x, int y)
1671 ghid_dialog_about ();
1672 return 0;
1675 /* ------------------------------------------------------------ */
1676 static const char getxy_syntax[] =
1677 "GetXY()";
1679 static const char getxy_help[] =
1680 "Get a coordinate.";
1682 /* %start-doc actions GetXY
1684 Prompts the user for a coordinate, if one is not already selected.
1686 %end-doc */
1688 static int
1689 GetXY (int argc, char **argv, int x, int y)
1691 return 0;
1694 /* ---------------------------------------------------------------------- */
1696 static int PointCursor (int argc, char **argv, int x, int y)
1698 if (!ghidgui)
1699 return 0;
1701 if (argc > 0)
1702 ghid_point_cursor ();
1703 else
1704 ghid_mode_cursor (Settings.Mode);
1705 return 0;
1708 /* ---------------------------------------------------------------------- */
1710 static int
1711 RouteStylesChanged (int argc, char **argv, int x, int y)
1713 gint n;
1715 if (PCB && PCB->RouteStyle[0].Name)
1716 for (n = 0; n < NUM_STYLES; ++n)
1717 ghid_route_style_set_button_label ((&PCB->RouteStyle[n])->Name, n);
1718 return 0;
1721 /* ---------------------------------------------------------------------- */
1724 PCBChanged (int argc, char **argv, int x, int y)
1726 if (!ghidgui)
1727 return 0;
1729 ghid_window_set_name_label (PCB->Name);
1731 if (!gport->pixmap)
1732 return 0;
1733 RouteStylesChanged (0, NULL, 0, 0);
1734 ghid_port_ranges_scale (TRUE);
1735 ghid_port_ranges_pan (0, 0, FALSE);
1736 ghid_port_ranges_zoom (0);
1737 ghid_port_ranges_changed ();
1738 ghid_sync_with_new_layout ();
1739 return 0;
1742 /* ---------------------------------------------------------------------- */
1744 static int
1745 LayerGroupsChanged (int argc, char **argv, int x, int y)
1747 printf ("LayerGroupsChanged -- not implemented\n");
1748 return 0;
1751 /* ---------------------------------------------------------------------- */
1753 static int
1754 LibraryChanged (int argc, char **argv, int x, int y)
1756 ghid_library_window_show (&ghid_port, FALSE);
1757 return 0;
1760 /* ---------------------------------------------------------------------- */
1762 static int
1763 Command (int argc, char **argv, int x, int y)
1765 ghid_handle_user_command (TRUE);
1766 return 0;
1769 /* ---------------------------------------------------------------------- */
1771 static int
1772 Load (int argc, char **argv, int x, int y)
1774 char *function;
1775 char *name = NULL;
1777 static gchar *current_element_dir = NULL;
1778 static gchar *current_layout_dir = NULL;
1779 static gchar *current_netlist_dir = NULL;
1781 /* we've been given the file name */
1782 if (argc > 1)
1783 return hid_actionv ("LoadFrom", argc, argv);
1785 function = argc ? argv[0] : "Layout";
1787 if (strcasecmp (function, "Netlist") == 0)
1789 name = ghid_dialog_file_select_open (_("Load netlist file"),
1790 &current_netlist_dir,
1791 Settings.FilePath);
1793 else if (strcasecmp (function, "ElementToBuffer") == 0)
1795 name = ghid_dialog_file_select_open (_("Load element to buffer"),
1796 &current_element_dir,
1797 Settings.LibraryTree);
1799 else if (strcasecmp (function, "LayoutToBuffer") == 0)
1801 name = ghid_dialog_file_select_open (_("Load layout file to buffer"),
1802 &current_layout_dir,
1803 Settings.FilePath);
1805 else if (strcasecmp (function, "Layout") == 0)
1807 name = ghid_dialog_file_select_open (_("Load layout file"),
1808 &current_layout_dir,
1809 Settings.FilePath);
1812 if (name)
1814 if (Settings.verbose)
1815 fprintf (stderr, "%s: Calling LoadFrom(%s, %s)\n", __FUNCTION__,
1816 function, name);
1817 hid_actionl ("LoadFrom", function, name, NULL);
1818 g_free (name);
1821 return 0;
1825 /* ---------------------------------------------------------------------- */
1826 static const char save_syntax[] =
1827 "Save()\n"
1828 "Save(Layout|LayoutAs)\n"
1829 "Save(AllConnections|AllUnusedPins|ElementConnections)\n"
1830 "Save(PasteBuffer)";
1832 static const char save_help[] =
1833 "Save layout and/or element data to a user-selected file.";
1835 /* %start-doc actions Save
1837 This action is a GUI front-end to the core's @code{SaveTo} action
1838 (@pxref{SaveTo Action}). If you happen to pass a filename, like
1839 @code{SaveTo}, then @code{SaveTo} is called directly. Else, the
1840 user is prompted for a filename to save, and then @code{SaveTo} is
1841 called with that filename.
1843 %end-doc */
1845 static int
1846 Save (int argc, char **argv, int x, int y)
1848 char *function;
1849 char *name;
1850 char *prompt;
1852 static gchar *current_dir = NULL;
1854 if (argc > 1)
1855 return hid_actionv ("SaveTo", argc, argv);
1857 function = argc ? argv[0] : "Layout";
1859 if (strcasecmp (function, "Layout") == 0)
1860 if (PCB->Filename)
1861 return hid_actionl ("SaveTo", "Layout", PCB->Filename, NULL);
1863 if (strcasecmp (function, "PasteBuffer") == 0)
1864 prompt = _("Save element as");
1865 else
1866 prompt = _("Save layout as");
1868 name = ghid_dialog_file_select_save (prompt,
1869 &current_dir,
1870 PCB->Filename, Settings.FilePath);
1872 if (name)
1874 FILE *exist;
1875 exist = fopen (name, "r");
1876 if (exist)
1878 fclose (exist);
1879 if (ghid_dialog_confirm (_("File exists! Ok to overwrite?"), NULL, NULL))
1881 if (Settings.verbose)
1882 fprintf (stderr, "Overwriting %s\n", name);
1884 else
1886 g_free (name);
1887 return 1;
1891 if (Settings.verbose)
1892 fprintf (stderr, "%s: Calling SaveTo(%s, %s)\n",
1893 __FUNCTION__, function, name);
1895 if (strcasecmp (function, "PasteBuffer") == 0)
1896 hid_actionl ("PasteBuffer", "Save", name, NULL);
1897 else
1900 * if we got this far and the function is Layout, then
1901 * we really needed it to be a LayoutAs. Otherwise
1902 * ActionSaveTo() will ignore the new file name we
1903 * just obtained.
1905 if (strcasecmp (function, "Layout") == 0)
1906 hid_actionl ("SaveTo", "LayoutAs", name, NULL);
1907 else
1908 hid_actionl ("SaveTo", function, name, NULL);
1910 g_free (name);
1912 else
1914 return 1;
1917 return 0;
1920 /* ---------------------------------------------------------------------- */
1921 static const char swapsides_syntax[] =
1922 "SwapSides(|v|h|r)";
1924 static const char swapsides_help[] =
1925 "Swaps the side of the board you're looking at.";
1927 /* %start-doc actions SwapSides
1929 This action changes the way you view the board.
1931 @table @code
1933 @item v
1934 Flips the board over vertically (up/down).
1936 @item h
1937 Flips the board over horizontally (left/right), like flipping pages in
1938 a book.
1940 @item r
1941 Rotates the board 180 degrees without changing sides.
1943 @end table
1945 If no argument is given, the board isn't moved but the opposite side
1946 is shown.
1948 Normally, this action changes which pads and silk layer are drawn as
1949 true silk, and which are drawn as the "invisible" layer. It also
1950 determines which solder mask you see.
1952 As a special case, if the layer group for the side you're looking at
1953 is visible and currently active, and the layer group for the opposite
1954 is not visible (i.e. disabled), then this action will also swap which
1955 layer group is visible and active, effectively swapping the ``working
1956 side'' of the board.
1958 %end-doc */
1961 static int
1962 SwapSides (int argc, char **argv, int x, int y)
1964 gint flipd;
1965 int do_flip_x = 0;
1966 int do_flip_y = 0;
1967 int comp_group = GetLayerGroupNumberByNumber (max_layer + COMPONENT_LAYER);
1968 int solder_group = GetLayerGroupNumberByNumber (max_layer + SOLDER_LAYER);
1969 int active_group = GetLayerGroupNumberByNumber (LayerStack[0]);
1970 int comp_showing =
1971 PCB->Data->Layer[PCB->LayerGroups.Entries[comp_group][0]].On;
1972 int solder_showing =
1973 PCB->Data->Layer[PCB->LayerGroups.Entries[solder_group][0]].On;
1976 if (argc > 0)
1978 switch (argv[0][0]) {
1979 case 'h':
1980 case 'H':
1981 ghid_flip_x = ! ghid_flip_x;
1982 do_flip_x = 1;
1983 break;
1984 case 'v':
1985 case 'V':
1986 ghid_flip_y = ! ghid_flip_y;
1987 do_flip_y = 1;
1988 break;
1989 case 'r':
1990 case 'R':
1991 ghid_flip_x = ! ghid_flip_x;
1992 ghid_flip_y = ! ghid_flip_y;
1993 do_flip_x = 1;
1994 do_flip_y = 1;
1995 break;
1996 default:
1997 return 1;
1999 /* SwapSides will swap this */
2000 Settings.ShowSolderSide = (ghid_flip_x == ghid_flip_y);
2003 Settings.ShowSolderSide = !Settings.ShowSolderSide;
2004 if (Settings.ShowSolderSide)
2006 if (active_group == comp_group && comp_showing && !solder_showing)
2008 ChangeGroupVisibility (PCB->LayerGroups.Entries[comp_group][0], 0,
2010 ChangeGroupVisibility (PCB->LayerGroups.Entries[solder_group][0], 1,
2014 else
2016 if (active_group == solder_group && solder_showing && !comp_showing)
2018 ChangeGroupVisibility (PCB->LayerGroups.Entries[solder_group][0], 0,
2020 ChangeGroupVisibility (PCB->LayerGroups.Entries[comp_group][0], 1,
2025 /* Update coordinates so that the current location stays where it was on the
2026 other side; we need to do this since the actual flip center is the
2027 center of the board while the user expect the center would be the current
2028 location */
2029 if (do_flip_x)
2031 flipd = PCB->MaxWidth / 2 - gport->view_x;
2032 ghid_port_ranges_pan (2 * flipd, 0, TRUE);
2034 if (do_flip_y)
2036 flipd = PCB->MaxHeight / 2 - gport->view_y;
2037 ghid_port_ranges_pan (0, 2 * flipd, TRUE);
2040 ghid_invalidate_all ();
2041 return 0;
2044 /* ------------------------------------------------------------ */
2046 static const char print_syntax[] =
2047 "Print()";
2049 static const char print_help[] =
2050 "Print the layout.";
2052 /* %start-doc actions Print
2054 This will find the default printing HID, prompt the user for its
2055 options, and print the layout.
2057 %end-doc */
2059 static int
2060 Print (int argc, char **argv, int x, int y)
2062 HID **hids;
2063 int i;
2064 HID *printer = NULL;
2066 hids = hid_enumerate ();
2067 for (i = 0; hids[i]; i++)
2069 if (hids[i]->printer)
2070 printer = hids[i];
2073 if (printer == NULL)
2075 gui->log (_("Can't find a suitable printer HID"));
2076 return -1;
2079 /* check if layout is empty */
2080 if (!IsDataEmpty (PCB->Data))
2082 ghid_dialog_print (printer);
2084 else
2085 gui->log (_("Can't print empty layout"));
2087 return 0;
2091 /* ------------------------------------------------------------ */
2093 static HID_Attribute
2094 printer_calibrate_attrs[] = {
2095 {"Enter Values here:", "",
2096 HID_Label, 0, 0, {0, 0, 0}, 0, 0},
2097 {"x-calibration", "X scale for calibrating your printer",
2098 HID_Real, 0.5, 25, {0, 0, 1.00}, 0, 0},
2099 {"y-calibration", "Y scale for calibrating your printer",
2100 HID_Real, 0.5, 25, {0, 0, 1.00}, 0, 0}
2102 static HID_Attr_Val printer_calibrate_values[3];
2104 static const char printcalibrate_syntax[] =
2105 "PrintCalibrate()";
2107 static const char printcalibrate_help[] =
2108 "Calibrate the printer.";
2110 /* %start-doc actions PrintCalibrate
2112 This will print a calibration page, which you would measure and type
2113 the measurements in, so that future printouts will be more precise.
2115 %end-doc */
2117 static int
2118 PrintCalibrate (int argc, char **argv, int x, int y)
2120 HID *printer = hid_find_printer ();
2121 printer->calibrate (0.0, 0.0);
2123 if (gui->attribute_dialog (printer_calibrate_attrs, 3,
2124 printer_calibrate_values,
2125 "Printer Calibration Values",
2126 "Enter calibration values for your printer"))
2127 return 1;
2128 printer->calibrate (printer_calibrate_values[1].real_value,
2129 printer_calibrate_values[2].real_value);
2130 return 0;
2133 /* ------------------------------------------------------------ */
2135 static int
2136 Export (int argc, char **argv, int x, int y)
2139 /* check if layout is empty */
2140 if (!IsDataEmpty (PCB->Data))
2142 ghid_dialog_export ();
2144 else
2145 gui->log (_("Can't export empty layout"));
2147 return 0;
2150 /* ------------------------------------------------------------ */
2152 static int
2153 Benchmark (int argc, char **argv, int x, int y)
2155 int i = 0;
2156 time_t start, end;
2157 BoxType region;
2158 GdkDisplay *display;
2160 display = gdk_drawable_get_display (gport->drawable);
2162 region.X1 = 0;
2163 region.Y1 = 0;
2164 region.X2 = PCB->MaxWidth;
2165 region.Y2 = PCB->MaxHeight;
2167 gdk_display_sync (display);
2168 time (&start);
2171 hid_expose_callback (&ghid_hid, &region, 0);
2172 gdk_display_sync (display);
2173 time (&end);
2174 i++;
2176 while (end - start < 10);
2178 printf ("%g redraws per second\n", i / 10.0);
2180 return 0;
2183 /* ------------------------------------------------------------ */
2185 static const char center_syntax[] =
2186 "Center()\n";
2188 static const char center_help[] =
2189 "Moves the pointer to the center of the window.";
2191 /* %start-doc actions Center
2193 Move the pointer to the center of the window, but only if it's
2194 currently within the window already.
2196 %end-doc */
2198 static int
2199 Center(int argc, char **argv, int x, int y)
2201 int x0, y0, w2, h2, dx, dy;
2203 if (argc != 0)
2204 AFAIL (center);
2206 x = GRIDFIT_X (SIDE_X (x), PCB->Grid);
2207 y = GRIDFIT_Y (SIDE_Y (y), PCB->Grid);
2209 w2 = gport->view_width / 2;
2210 h2 = gport->view_height / 2;
2211 x0 = x - w2;
2212 y0 = y - h2;
2214 if (x0 < 0)
2216 x0 = 0;
2217 x = x0 + w2;
2220 if (y0 < 0)
2222 y0 = 0;
2223 y = y0 + w2;
2226 dx = (x0 - gport->view_x0) / gport->zoom ;
2227 dy = (y0 - gport->view_y0) / gport->zoom;
2228 gport->view_x0 = x0;
2229 gport->view_y0 = y0;
2232 ghid_pan_fixup ();
2234 /* Move the pointer to the center of the window, but only if it's
2235 currently within the window already. Watch out for edges,
2236 though. */
2238 #if GTK_CHECK_VERSION(2,8,0)
2240 GdkDisplay *display;
2241 GdkScreen *screen;
2242 gint cx, cy;
2244 display = gdk_display_get_default ();
2245 screen = gdk_display_get_default_screen (display);
2247 /* figure out where the pointer is and then move it from there by the specified delta */
2248 gdk_display_get_pointer (display, NULL, &cx, &cy, NULL);
2249 gdk_display_warp_pointer (display, screen, cx - dx, cy - dy);
2252 * Note that under X11, gdk_display_warp_pointer is just a wrapper around XWarpPointer, but
2253 * hopefully by avoiding the direct call to an X function we might still work under windows
2254 * and other non-X11 based gdk's
2257 #else
2258 # ifdef HAVE_GDK_GDKX_H
2261 Window w_src, w_dst;
2262 w_src = GDK_WINDOW_XID (gport->drawing_area->window);
2263 w_dst = w_src;
2265 /* don't warp with the auto drc - that creates auto-scroll chaos */
2266 if (TEST_FLAG (AUTODRCFLAG, PCB) && Settings.Mode == LINE_MODE
2267 && Crosshair.AttachedLine.State != STATE_FIRST)
2268 return 0;
2270 XWarpPointer (GDK_DRAWABLE_XDISPLAY (gport->drawing_area->window),
2271 w_src, w_dst,
2272 0, 0, 0, 0,
2273 Vx2 (x), Vy2 (y));
2275 /* XWarpPointer creates Motion events normally bound to
2276 * EventMoveCrosshair.
2277 * We don't do any updates when EventMoveCrosshair
2278 * is called the next time to prevent from rounding errors
2280 /* FIXME?
2281 * IgnoreMotionEvents = ignore;
2284 # endif
2285 #endif
2287 return 0;
2290 /* ------------------------------------------------------------ */
2291 static const char cursor_syntax[] =
2292 "Cursor(Type,DeltaUp,DeltaRight,Units)";
2294 static const char cursor_help[] =
2295 "Move the cursor.";
2297 /* %start-doc actions Cursor
2299 This action moves the mouse cursor. Unlike other actions which take
2300 coordinates, this action's coordinates are always relative to the
2301 user's view of the board. Thus, a positive @var{DeltaUp} may move the
2302 cursor towards the board origin if the board is inverted.
2304 Type is one of @samp{Pan} or @samp{Warp}. @samp{Pan} causes the
2305 viewport to move such that the crosshair is under the mouse cursor.
2306 @samp{Warp} causes the mouse cursor to move to be above the crosshair.
2308 @var{Units} can be one of the following:
2310 @table @samp
2312 @item mil
2313 @itemx mm
2314 The cursor is moved by that amount, in board units.
2316 @item grid
2317 The cursor is moved by that many grid points.
2319 @item view
2320 The values are percentages of the viewport's view. Thus, a pan of
2321 @samp{100} would scroll the viewport by exactly the width of the
2322 current view.
2324 @item board
2325 The values are percentages of the board size. Thus, a move of
2326 @samp{50,50} moves you halfway across the board.
2328 @end table
2330 %end-doc */
2332 static int
2333 CursorAction(int argc, char **argv, int x, int y)
2335 int pan_warp = HID_SC_DO_NOTHING;
2336 double dx, dy;
2337 double xu = 0.0, yu = 0.0;
2339 if (argc != 4)
2340 AFAIL (cursor);
2342 if (strcasecmp (argv[0], "pan") == 0)
2343 pan_warp = HID_SC_PAN_VIEWPORT;
2344 else if (strcasecmp (argv[0], "warp") == 0)
2345 pan_warp = HID_SC_WARP_POINTER;
2346 else
2347 AFAIL (cursor);
2349 dx = strtod (argv[1], 0);
2350 if (ghid_flip_x)
2351 dx = -dx;
2352 dy = strtod (argv[2], 0);
2353 if (!ghid_flip_y)
2354 dy = -dy;
2357 * xu and yu are the scale factors that we multiply dx and dy by to
2358 * come up with PCB internal units.
2360 if (strncasecmp (argv[3], "mm", 2) == 0)
2361 xu = yu = MM_TO_COOR;
2362 else if (strncasecmp (argv[3], "mil", 3) == 0)
2363 xu = yu = 100;
2364 else if (strncasecmp (argv[3], "grid", 4) == 0)
2365 xu = yu = PCB->Grid;
2366 else if (strncasecmp (argv[3], "view", 4) == 0)
2368 xu = gport->view_width / 100.0;
2369 yu = gport->view_height / 100.0;
2371 else if (strncasecmp (argv[3], "board", 4) == 0)
2373 xu = PCB->MaxWidth / 100.0;
2374 yu = PCB->MaxHeight / 100.0;
2377 EventMoveCrosshair (Crosshair.X+(int)(dx*xu), Crosshair.Y+(int)(dy*yu));
2378 gui->set_crosshair (Crosshair.X, Crosshair.Y, pan_warp);
2380 return 0;
2382 /* ------------------------------------------------------------ */
2384 static const char dowindows_syntax[] =
2385 "DoWindows(1|2|3|4)\n"
2386 "DoWindows(Layout|Library|Log|Netlist|Preferences)";
2388 static const char dowindows_help[] =
2389 "Open various GUI windows.";
2391 /* %start-doc actions DoWindows
2393 @table @code
2395 @item 1
2396 @itemx Layout
2397 Open the layout window. Since the layout window is always shown
2398 anyway, this has no effect.
2400 @item 2
2401 @itemx Library
2402 Open the library window.
2404 @item 3
2405 @itemx Log
2406 Open the log window.
2408 @item 4
2409 @itemx Netlist
2410 Open the netlist window.
2412 @item 5
2413 @itemx Preferences
2414 Open the preferences window.
2416 @end table
2418 %end-doc */
2420 static int
2421 DoWindows (int argc, char **argv, int x, int y)
2423 char *a = argc == 1 ? argv[0] : "";
2425 if (strcmp (a, "1") == 0 || strcasecmp (a, "Layout") == 0)
2428 else if (strcmp (a, "2") == 0 || strcasecmp (a, "Library") == 0)
2430 ghid_library_window_show (gport, TRUE);
2432 else if (strcmp (a, "3") == 0 || strcasecmp (a, "Log") == 0)
2434 ghid_log_window_show (TRUE);
2436 else if (strcmp (a, "4") == 0 || strcasecmp (a, "Netlist") == 0)
2438 ghid_netlist_window_show (gport, TRUE);
2440 else if (strcmp (a, "5") == 0 || strcasecmp (a, "Preferences") == 0)
2442 ghid_config_window_show ();
2444 else
2446 AFAIL (dowindows);
2449 return 0;
2452 /* ------------------------------------------------------------ */
2453 static const char setunits_syntax[] =
2454 "SetUnits(mm|mil)";
2456 static const char setunits_help[] =
2457 "Set the default measurement units.";
2459 /* %start-doc actions SetUnits
2461 @table @code
2463 @item mil
2464 Sets the display units to mils (1/1000 inch).
2466 @item mm
2467 Sets the display units to millimeters.
2469 @end table
2471 %end-doc */
2473 static int
2474 SetUnits (int argc, char **argv, int x, int y)
2476 if (argc == 0)
2477 return 0;
2478 if (strcmp (argv[0], "mil") == 0)
2479 Settings.grid_units_mm = 0;
2480 if (strcmp (argv[0], "mm") == 0)
2481 Settings.grid_units_mm = 1;
2483 ghid_config_handle_units_changed ();
2485 ghid_set_status_line_label ();
2487 /* FIXME ?
2488 * lesstif_sizes_reset ();
2489 * lesstif_styles_update_values ();
2491 return 0;
2494 /* ------------------------------------------------------------ */
2495 static const char popup_syntax[] =
2496 "Popup(MenuName, [Button])";
2498 static const char popup_help[] =
2499 "Bring up the popup menu specified by @code{MenuName}.\n"
2500 "If called by a mouse event then the mouse button number\n"
2501 "must be specified as the optional second argument.";
2503 /* %start-doc actions Popup
2505 This just pops up the specified menu. The menu must have been defined
2506 as a named subresource of the Popups resource in the menu resource
2507 file. If called as a response to a mouse button click, the mouse
2508 button number must be specified as the second argument.
2510 %end-doc */
2513 static int
2514 Popup (int argc, char **argv, int x, int y)
2516 GtkWidget *menu;
2517 char *element;
2518 guint button;
2520 if (argc != 1 && argc != 2)
2521 AFAIL (popup);
2523 if (argc == 1)
2524 button = 0;
2525 else
2526 button = atoi (argv[1]);
2528 if ( (element = (char *) malloc ( (strlen (argv[0]) + 2) * sizeof (char))) == NULL )
2530 fprintf (stderr, "Popup(): malloc failed\n");
2531 exit (1);
2534 sprintf (element, "/%s", argv[0]);
2535 printf ("Loading popup \"%s\". Button = %u\n", element, button);
2537 menu = gtk_ui_manager_get_widget (ghidgui->ui_manager, element);
2538 free (element);
2540 if (! GTK_IS_MENU (menu))
2542 Message ("The specified popup menu \"%s\" has not been defined.\n", argv[0]);
2543 return 1;
2545 else
2547 ghidgui->in_popup = TRUE;
2548 gtk_widget_grab_focus (ghid_port.drawing_area);
2549 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0,
2550 gtk_get_current_event_time());
2552 return 0;
2555 static int
2556 Busy (int argc, char **argv, int x, int y)
2558 ghid_watch_cursor ();
2559 return 0;
2562 HID_Action ghid_main_action_list[] = {
2563 {"About", 0, About, about_help, about_syntax},
2564 {"Benchmark", 0, Benchmark},
2565 {"Busy", 0, Busy},
2566 {"Center", "Click on a location to center", Center, center_help, center_syntax},
2567 {"Command", 0, Command},
2568 {"Cursor", 0, CursorAction, cursor_help, cursor_syntax},
2569 {"DoWindows", 0, DoWindows, dowindows_help, dowindows_syntax},
2570 {"Export", 0, Export},
2571 {"GetXY", "", GetXY, getxy_help, getxy_syntax},
2572 {"LayerGroupsChanged", 0, LayerGroupsChanged},
2573 {"LibraryChanged", 0, LibraryChanged},
2574 {"Load", 0, Load},
2575 {"PCBChanged", 0, PCBChanged},
2576 {"PointCursor", 0, PointCursor},
2577 {"Popup", 0, Popup, popup_help, popup_syntax},
2578 {"Print", 0, Print,
2579 print_help, print_syntax},
2580 {"PrintCalibrate", 0, PrintCalibrate,
2581 printcalibrate_help, printcalibrate_syntax},
2582 {"RouteStylesChanged", 0, RouteStylesChanged},
2583 {"Save", 0, Save, save_help, save_syntax},
2584 {"SetUnits", 0, SetUnits, setunits_help, setunits_syntax},
2585 {"SwapSides", 0, SwapSides, swapsides_help, swapsides_syntax},
2586 {"Zoom", "Click on zoom focus", Zoom, zoom_help, zoom_syntax}
2589 REGISTER_ACTIONS (ghid_main_action_list)
2592 static int
2593 flag_flipx (int x)
2595 return ghid_flip_x;
2597 static int
2598 flag_flipy (int x)
2600 return ghid_flip_y;
2603 HID_Flag ghid_main_flag_list[] = {
2604 {"flip_x", flag_flipx, 0},
2605 {"flip_y", flag_flipy, 0}
2608 REGISTER_FLAGS (ghid_main_flag_list)
2610 #include "dolists.h"
2613 * We will need these for finding the windows installation
2614 * directory. Without that we can't find our fonts and
2615 * footprint libraries.
2617 #ifdef WIN32
2618 #include <windows.h>
2619 #include <winreg.h>
2620 #endif
2622 void
2623 hid_gtk_init ()
2625 #ifdef WIN32
2627 char * tmps;
2628 char * share_dir;
2630 tmps = g_win32_get_package_installation_directory (PACKAGE "-" VERSION, NULL);
2631 #define REST_OF_PATH G_DIR_SEPARATOR_S "share" G_DIR_SEPARATOR_S PACKAGE
2632 share_dir = (char *) malloc(strlen(tmps) +
2633 strlen(REST_OF_PATH) +
2635 sprintf (share_dir, "%s%s", tmps, REST_OF_PATH);
2636 free (tmps);
2637 #undef REST_OF_PATH
2638 printf ("\"Share\" installation path is \"%s\"\n", share_dir);
2639 #endif
2641 hid_register_hid (&ghid_hid);
2642 apply_default_hid (&ghid_extents, &ghid_hid);
2643 #include "gtk_lists.h"