GTK HID: Raise already open command window to top with ":" key
[geda-pcb/gde.git] / src / hid / gtk / gtkhid-main.c
blob09d8025d13d4fedccfdf6f96d7fd8778e3ed41c8
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 "action.h"
17 #include "crosshair.h"
18 #include "data.h"
19 #include "draw.h"
20 #include "error.h"
21 #include "global.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"
31 #if !GTK_CHECK_VERSION(2,8,0) && defined(HAVE_GDK_GDKX_H)
32 #include <gdk/gdkx.h>
33 #endif
35 #ifdef HAVE_LIBDMALLOC
36 #include <dmalloc.h>
37 #endif
40 RCSID ("$Id$");
43 extern HID ghid_hid;
46 static void zoom_to (double factor, int x, int y);
47 static void zoom_by (double factor, int x, int y);
49 /* Sets gport->u_gc to the "right" GC to use (wrt mask or window)
51 #define USE_GC(gc) if (!use_gc(gc)) return
53 static int cur_mask = -1;
54 static int mask_seq = 0;
56 int ghid_flip_x = 0, ghid_flip_y = 0;
58 /* ------------------------------------------------------------ */
60 /* Px converts view->pcb, Vx converts pcb->view */
62 static inline int
63 Vx (int x)
65 int rv;
66 if (ghid_flip_x)
67 rv = (PCB->MaxWidth - x - gport->view_x0) / gport->zoom + 0.5;
68 else
69 rv = (x - gport->view_x0) / gport->zoom + 0.5;
70 return rv;
73 static inline int
74 Vx2 (int x)
76 return (x - gport->view_x0) / gport->zoom + 0.5;
79 static inline int
80 Vy (int y)
82 int rv;
83 if (ghid_flip_y)
84 rv = (PCB->MaxHeight - y - gport->view_y0) / gport->zoom + 0.5;
85 else
86 rv = (y - gport->view_y0) / gport->zoom + 0.5;
87 return rv;
90 static inline int
91 Vy2 (int y)
93 return (y - gport->view_y0) / gport->zoom + 0.5;
96 static inline int
97 Vz (int z)
99 return z / gport->zoom + 0.5;
102 static inline int
103 Px (int x)
105 int rv = x * gport->zoom + gport->view_x0;
106 if (ghid_flip_x)
107 rv = PCB->MaxWidth - (x * gport->zoom + gport->view_x0);
108 return rv;
111 static inline int
112 Py (int y)
114 int rv = y * gport->zoom + gport->view_y0;
115 if (ghid_flip_y)
116 rv = PCB->MaxHeight - (y * gport->zoom + gport->view_y0);
117 return rv;
120 static inline int
121 Pz (int z)
123 return (z * gport->zoom);
126 /* ------------------------------------------------------------ */
128 static void
129 ghid_pan_fixup ()
133 * don't pan so far to the right that we see way past the right
134 * edge of the board.
136 if (gport->view_x0 > PCB->MaxWidth - gport->view_width)
137 gport->view_x0 = PCB->MaxWidth - gport->view_width;
140 * don't pan so far down that we see way past the bottom edge of
141 * the board.
143 if (gport->view_y0 > PCB->MaxHeight - gport->view_height)
144 gport->view_y0 = PCB->MaxHeight - gport->view_height;
146 /* don't view above or to the left of the board... ever */
147 if (gport->view_x0 < 0)
148 gport->view_x0 = 0;
150 if (gport->view_y0 < 0)
151 gport->view_y0 = 0;
154 /* if we can see the entire board and some, then zoom to fit */
155 if (gport->view_width > PCB->MaxWidth &&
156 gport->view_height > PCB->MaxHeight)
158 zoom_by (1, 0, 0);
159 return;
162 gtk_range_set_value (GTK_RANGE (ghidgui->h_range), gport->view_x0);
163 gtk_range_set_value (GTK_RANGE (ghidgui->v_range), gport->view_y0);
165 ghid_invalidate_all ();
169 /* ------------------------------------------------------------ */
171 static const char zoom_syntax[] =
172 "Zoom()\n"
173 "Zoom(factor)";
176 static const char zoom_help[] =
177 "Various zoom factor changes.";
179 /* %start-doc actions Zoom
180 Changes the zoom (magnification) of the view of the board. If no
181 arguments are passed, the view is scaled such that the board just fits
182 inside the visible window (i.e. ``view all''). Otherwise,
183 @var{factor} specifies a change in zoom factor. It may be prefixed by
184 @code{+}, @code{-}, or @code{=} to change how the zoom factor is
185 modified. The @var{factor} is a floating point number, such as
186 @code{1.5} or @code{0.75}.
188 @table @code
190 @item +@var{factor}
191 Values greater than 1.0 cause the board to be drawn smaller; more of
192 the board will be visible. Values between 0.0 and 1.0 cause the board
193 to be drawn bigger; less of the board will be visible.
195 @item -@var{factor}
196 Values greater than 1.0 cause the board to be drawn bigger; less of
197 the board will be visible. Values between 0.0 and 1.0 cause the board
198 to be drawn smaller; more of the board will be visible.
200 @item =@var{factor}
202 The @var{factor} is an absolute zoom factor; the unit for this value
203 is "PCB units per screen pixel". Since PCB units are 0.01 mil, a
204 @var{factor} of 1000 means 10 mils (0.01 in) per pixel, or 100 DPI,
205 about the actual resolution of most screens - resulting in an "actual
206 size" board. Similarly, a @var{factor} of 100 gives you a 10x actual
207 size.
209 @end table
211 Note that zoom factors of zero are silently ignored.
215 %end-doc */
217 static int
218 Zoom (int argc, char **argv, int x, int y)
220 double factor;
221 const char *vp;
222 double v;
224 if (argc > 1)
225 AFAIL (zoom);
227 if (x == 0 && y == 0)
229 x = gport->view_width / 2;
230 y = gport->view_height / 2;
232 else
234 /* Px converts view->pcb, Vx converts pcb->view */
235 x = Vx (x);
236 y = Vy (y);
239 if (argc < 1)
241 zoom_to (1000000, 0, 0);
242 return 0;
245 vp = argv[0];
246 if (*vp == '+' || *vp == '-' || *vp == '=')
247 vp++;
248 v = strtod (vp, 0);
249 if (v <= 0)
250 return 1;
251 switch (argv[0][0])
253 case '-':
254 factor = 1 / v;
255 zoom_by (1 / v, x, y);
256 break;
257 default:
258 case '+':
259 factor = v;
260 zoom_by (v, x, y);
261 break;
262 case '=':
263 /* this needs to set the scale factor absolutely*/
264 factor = 1.0;
265 zoom_to (v, x, y);
266 break;
269 return 0;
273 static void
274 zoom_to (double new_zoom, int x, int y)
276 double max_zoom, xfrac, yfrac;
277 int cx, cy;
279 /* gport->zoom:
280 * zoom value is PCB units per screen pixel. Larger numbers mean zooming
281 * out - the largest value means you are looking at the whole board.
283 * PCB units per screen pixel
285 * gport->view_width and gport->view_height are in PCB coordinates
288 #ifdef DEBUG
289 printf ("\nzoom_to( %g, %d, %d)\n", new_zoom, x, y);
290 #endif
292 xfrac = (double) x / (double) gport->view_width;
293 yfrac = (double) y / (double) gport->view_height;
295 if (ghid_flip_x)
296 xfrac = 1-xfrac;
297 if (ghid_flip_y)
298 yfrac = 1-yfrac;
300 /* Find the zoom that would just make the entire board fit */
301 max_zoom = PCB->MaxWidth / gport->width;
302 if (max_zoom < PCB->MaxHeight / gport->height)
303 max_zoom = PCB->MaxHeight / gport->height;
305 #ifdef DEBUG
306 printf ("zoom_to(): max_zoom = %g\n", max_zoom);
307 #endif
310 * clip the zooming so we can never have more than 1 pixel per PCB
311 * unit and never zoom out more than viewing the entire board
314 if (new_zoom < 1)
315 new_zoom = 1;
316 if (new_zoom > max_zoom)
317 new_zoom = max_zoom;
319 #ifdef DEBUG
320 printf ("max_zoom = %g, xfrac = %g, yfrac = %g, new_zoom = %g\n",
321 max_zoom, xfrac, yfrac, new_zoom);
322 #endif
324 /* find center x and y */
325 cx = gport->view_x0 + gport->view_width * xfrac * gport->zoom;
326 cy = gport->view_y0 + gport->view_height * yfrac * gport->zoom;
328 #ifdef DEBUG
329 printf ("zoom_to(): x0 = %d, cx = %d\n", gport->view_x0, cx);
330 printf ("zoom_to(): y0 = %d, cy = %d\n", gport->view_y0, cy);
331 #endif
333 if (gport->zoom != new_zoom)
335 gdouble xtmp, ytmp;
336 gint x0, y0;
338 xtmp = (gport->view_x - gport->view_x0) / (gdouble) gport->view_width;
339 ytmp = (gport->view_y - gport->view_y0) / (gdouble) gport->view_height;
341 gport->zoom = new_zoom;
342 pixel_slop = new_zoom;
343 ghid_port_ranges_scale(FALSE);
345 x0 = gport->view_x - xtmp * gport->view_width;
346 if (x0 < 0)
347 x0 = 0;
348 gport->view_x0 = x0;
350 y0 = gport->view_y - ytmp * gport->view_height;
351 if (y0 < 0)
352 y0 = 0;
353 gport->view_y0 = y0;
355 ghidgui->adjustment_changed_holdoff = TRUE;
356 gtk_range_set_value (GTK_RANGE (ghidgui->h_range), gport->view_x0);
357 gtk_range_set_value (GTK_RANGE (ghidgui->v_range), gport->view_y0);
358 ghidgui->adjustment_changed_holdoff = FALSE;
360 ghid_port_ranges_changed();
363 #ifdef DEBUG
364 printf ("zoom_to(): new x0 = %d\n", gport->view_x0);
365 printf ("zoom_to(): new y0 = %d\n", gport->view_y0);
366 #endif
367 ghid_set_status_line_label ();
370 void
371 zoom_by (double factor, int x, int y)
373 #ifdef DEBUG
374 printf ("\nzoom_by( %g, %d, %d). old gport->zoom = %g\n",
375 factor, x, y, gport->zoom);
376 #endif
377 zoom_to (gport->zoom * factor, x, y);
380 /* ------------------------------------------------------------ */
382 static void
383 draw_grid ()
385 static GdkPoint *points = 0;
386 static int npoints = 0;
387 int x1, y1, x2, y2, n, i;
388 double x, y;
390 if (!Settings.DrawGrid)
391 return;
392 if (Vz (PCB->Grid) < MIN_GRID_DISTANCE)
393 return;
394 if (!gport->grid_gc)
396 if (gdk_color_parse (Settings.GridColor, &gport->grid_color))
398 gport->grid_color.red ^= gport->bg_color.red;
399 gport->grid_color.green ^= gport->bg_color.green;
400 gport->grid_color.blue ^= gport->bg_color.blue;
401 gdk_color_alloc (gport->colormap, &gport->grid_color);
403 gport->grid_gc = gdk_gc_new (gport->drawable);
404 gdk_gc_set_function (gport->grid_gc, GDK_XOR);
405 gdk_gc_set_foreground (gport->grid_gc, &gport->grid_color);
407 x1 = GRIDFIT_X (SIDE_X (gport->view_x0), PCB->Grid);
408 y1 = GRIDFIT_Y (SIDE_Y (gport->view_y0), PCB->Grid);
409 x2 = GRIDFIT_X (SIDE_X (gport->view_x0 + gport->view_width - 1), PCB->Grid);
410 y2 = GRIDFIT_Y (SIDE_Y (gport->view_y0 + gport->view_height - 1), PCB->Grid);
411 if (x1 > x2)
413 int tmp = x1;
414 x1 = x2;
415 x2 = tmp;
417 if (y1 > y2)
419 int tmp = y1;
420 y1 = y2;
421 y2 = tmp;
423 if (Vx (x1) < 0)
424 x1 += PCB->Grid;
425 if (Vy (y1) < 0)
426 y1 += PCB->Grid;
427 if (Vx (x2) >= gport->width)
428 x2 -= PCB->Grid;
429 if (Vy (y2) >= gport->height)
430 y2 -= PCB->Grid;
431 n = (int) ((x2 - x1) / PCB->Grid + 0.5) + 1;
432 if (n > npoints)
434 npoints = n + 10;
435 points =
436 MyRealloc (points, npoints * sizeof (GdkPoint), "gtk_draw_grid");
438 n = 0;
439 for (x = x1; x <= x2; x += PCB->Grid)
441 points[n].x = Vx (x);
442 n++;
444 for (y = y1; y <= y2; y += PCB->Grid)
446 int vy = Vy (y);
447 for (i = 0; i < n; i++)
448 points[i].y = vy;
449 gdk_draw_points (gport->drawable, gport->grid_gc, points, n);
453 /* ------------------------------------------------------------ */
455 HID_Attribute *
456 ghid_get_export_options (int *n_ret)
458 return NULL;
462 void
463 ghid_invalidate_wh (int x, int y, int width, int height, int last)
465 ghid_invalidate_all ();
468 void
469 ghid_invalidate_lr (int left, int right, int top, int bottom, int last)
471 ghid_invalidate_all ();
474 static void
475 ghid_draw_bg_image(void)
477 static GdkPixbuf *pixbuf;
478 GdkInterpType interp_type;
479 gint x, y, w, h, w_src, h_src;
480 static gint w_scaled, h_scaled;
482 if (!ghidgui->bg_pixbuf)
483 return;
485 w = PCB->MaxWidth / gport->zoom;
486 h = PCB->MaxHeight / gport->zoom;
487 x = gport->view_x0 / gport->zoom;
488 y = gport->view_y0 / gport->zoom;
490 if (w_scaled != w || h_scaled != h)
492 if (pixbuf)
493 g_object_unref(G_OBJECT(pixbuf));
495 w_src = gdk_pixbuf_get_width(ghidgui->bg_pixbuf);
496 h_src = gdk_pixbuf_get_height(ghidgui->bg_pixbuf);
497 if (w > w_src && h > h_src)
498 interp_type = GDK_INTERP_NEAREST;
499 else
500 interp_type = GDK_INTERP_BILINEAR;
502 pixbuf = gdk_pixbuf_scale_simple(ghidgui->bg_pixbuf, w, h, interp_type);
503 w_scaled = w;
504 h_scaled = h;
506 if (pixbuf)
507 gdk_pixbuf_render_to_drawable(pixbuf, gport->drawable, gport->bg_gc,
508 x, y, 0, 0,
509 w - x, h - y, GDK_RGB_DITHER_NORMAL, 0, 0);
512 void
513 ghid_invalidate_all ()
515 int eleft, eright, etop, ebottom;
516 BoxType region;
518 if (!gport->pixmap)
519 return;
521 region.X1 = MIN(Px(0), Px(gport->width + 1));
522 region.Y1 = MIN(Py(0), Py(gport->height + 1));
523 region.X2 = MAX(Px(0), Px(gport->width + 1));
524 region.Y2 = MAX(Py(0), Py(gport->height + 1));
526 eleft = Vx (0);
527 eright = Vx (PCB->MaxWidth);
528 etop = Vy (0);
529 ebottom = Vy (PCB->MaxHeight);
530 if (eleft > eright)
532 int tmp = eleft;
533 eleft = eright;
534 eright = tmp;
536 if (etop > ebottom)
538 int tmp = etop;
539 etop = ebottom;
540 ebottom = tmp;
543 if (eleft > 0)
544 gdk_draw_rectangle (gport->drawable, gport->offlimits_gc,
545 1, 0, 0, eleft, gport->height);
546 else
547 eleft = 0;
548 if (eright < gport->width)
549 gdk_draw_rectangle (gport->drawable, gport->offlimits_gc,
550 1, eright, 0, gport->width - eright, gport->height);
551 else
552 eright = gport->width;
553 if (etop > 0)
554 gdk_draw_rectangle (gport->drawable, gport->offlimits_gc,
555 1, eleft, 0, eright - eleft + 1, etop);
556 else
557 etop = 0;
558 if (ebottom < gport->height)
559 gdk_draw_rectangle (gport->drawable, gport->offlimits_gc,
560 1, eleft, ebottom, eright - eleft + 1,
561 gport->height - ebottom);
562 else
563 ebottom = gport->height;
565 gdk_draw_rectangle (gport->drawable, gport->bg_gc, 1,
566 eleft, etop, eright - eleft + 1, ebottom - etop + 1);
568 ghid_draw_bg_image();
570 hid_expose_callback (&ghid_hid, &region, 0);
571 draw_grid ();
572 if (ghidgui->need_restore_crosshair)
573 RestoreCrosshair (FALSE);
574 ghidgui->need_restore_crosshair = FALSE;
575 ghid_screen_update ();
580 ghid_set_layer (const char *name, int group)
582 int idx = (group >= 0
583 && group <
584 max_layer) ? PCB->LayerGroups.Entries[group][0] : group;
586 if (idx >= 0 && idx < max_layer + 2)
587 return /*pinout ? 1 : */ PCB->Data->Layer[idx].On;
588 if (idx < 0)
590 switch (SL_TYPE (idx))
592 case SL_INVISIBLE:
593 return /* pinout ? 0 : */ PCB->InvisibleObjectsOn;
594 case SL_MASK:
595 if (SL_MYSIDE (idx) /*&& !pinout */ )
596 return TEST_FLAG (SHOWMASKFLAG, PCB);
597 return 0;
598 case SL_SILK:
599 if (SL_MYSIDE (idx) /*|| pinout */ )
600 return PCB->ElementOn;
601 return 0;
602 case SL_ASSY:
603 return 0;
604 case SL_PDRILL:
605 case SL_UDRILL:
606 return 1;
609 return 0;
612 #define WHICH_GC(gc) (cur_mask == HID_MASK_CLEAR ? gport->mask_gc : (gc)->gc)
614 void
615 ghid_use_mask (int use_it)
617 static int mask_seq_id = 0;
618 GdkColor color;
620 if (!gport->pixmap)
621 return;
622 if (use_it == cur_mask)
623 return;
624 switch (use_it)
626 case HID_MASK_OFF:
627 gport->drawable = gport->pixmap;
628 mask_seq = 0;
629 break;
631 case HID_MASK_BEFORE:
632 printf ("gtk doesn't support mask_before!\n");
633 abort ();
635 case HID_MASK_CLEAR:
636 if (!gport->mask)
637 gport->mask = gdk_pixmap_new (0, gport->width, gport->height, 1);
638 gport->drawable = gport->mask;
639 mask_seq = 0;
640 if (!gport->mask_gc)
642 gport->mask_gc = gdk_gc_new (gport->drawable);
644 color.pixel = 1;
645 gdk_gc_set_foreground (gport->mask_gc, &color);
646 gdk_draw_rectangle (gport->drawable, gport->mask_gc, TRUE, 0, 0,
647 gport->width, gport->height);
648 color.pixel = 0;
649 gdk_gc_set_foreground (gport->mask_gc, &color);
650 break;
652 case HID_MASK_AFTER:
653 mask_seq_id++;
654 if (!mask_seq_id)
655 mask_seq_id = 1;
656 mask_seq = mask_seq_id;
658 gport->drawable = gport->pixmap;
659 break;
662 cur_mask = use_it;
665 void
666 ghid_extents_use_mask (int use_it)
671 typedef struct
673 int color_set;
674 GdkColor color;
675 int xor_set;
676 GdkColor xor_color;
677 } ColorCache;
680 /* Config helper functions for when the user changes color preferences.
681 | set_special colors used in the gtkhid.
683 static void
684 set_special_grid_color (void)
686 if (!gport->colormap)
687 return;
688 gport->grid_color.red ^= gport->bg_color.red;
689 gport->grid_color.green ^= gport->bg_color.green;
690 gport->grid_color.blue ^= gport->bg_color.blue;
691 gdk_color_alloc (gport->colormap, &gport->grid_color);
692 if (gport->grid_gc)
693 gdk_gc_set_foreground (gport->grid_gc, &gport->grid_color);
696 void
697 ghid_set_special_colors (HID_Attribute * ha)
699 if (!ha->name || !ha->value)
700 return;
701 if (!strcmp (ha->name, "background-color") && gport->bg_gc)
703 ghid_map_color_string (*(char **) ha->value, &gport->bg_color);
704 gdk_gc_set_foreground (gport->bg_gc, &gport->bg_color);
705 set_special_grid_color ();
707 else if (!strcmp (ha->name, "off-limit-color") && gport->offlimits_gc)
709 ghid_map_color_string (*(char **) ha->value, &gport->offlimits_color);
710 gdk_gc_set_foreground (gport->offlimits_gc, &gport->offlimits_color);
712 else if (!strcmp (ha->name, "grid-color") && gport->grid_gc)
714 ghid_map_color_string (*(char **) ha->value, &gport->grid_color);
715 set_special_grid_color ();
719 void
720 ghid_set_color (hidGC gc, const char *name)
722 static void *cache = 0;
723 hidval cval;
725 if (name == NULL)
727 fprintf (stderr, "%s(): name = NULL, setting to magenta\n",
728 __FUNCTION__);
729 name = "magenta";
732 gc->colorname = (char *) name;
733 if (!gc->gc)
734 return;
735 if (gport->colormap == 0)
736 gport->colormap = gtk_widget_get_colormap (gport->top_window);
738 if (strcmp (name, "erase") == 0)
740 gdk_gc_set_foreground (gc->gc, &gport->bg_color);
741 gc->erase = 1;
743 else if (strcmp (name, "drill") == 0)
745 gdk_gc_set_foreground (gc->gc, &gport->offlimits_color);
746 gc->erase = 0;
748 else
750 ColorCache *cc;
751 if (hid_cache_color (0, name, &cval, &cache))
752 cc = (ColorCache *) cval.ptr;
753 else
755 cc = (ColorCache *) malloc (sizeof (ColorCache));
756 memset (cc, 0, sizeof (*cc));
757 cval.ptr = cc;
758 hid_cache_color (1, name, &cval, &cache);
761 if (!cc->color_set)
763 if (gdk_color_parse (name, &cc->color))
764 gdk_color_alloc (gport->colormap, &cc->color);
765 else
766 gdk_color_white (gport->colormap, &cc->color);
767 cc->color_set = 1;
769 if (gc->xor)
771 if (!cc->xor_set)
773 cc->xor_color.red = cc->color.red ^ gport->bg_color.red;
774 cc->xor_color.green = cc->color.green ^ gport->bg_color.green;
775 cc->xor_color.blue = cc->color.blue ^ gport->bg_color.blue;
776 gdk_color_alloc (gport->colormap, &cc->xor_color);
777 cc->xor_set = 1;
779 gdk_gc_set_foreground (gc->gc, &cc->xor_color);
781 else
783 gdk_gc_set_foreground (gc->gc, &cc->color);
786 gc->erase = 0;
790 void
791 ghid_set_line_cap (hidGC gc, EndCapStyle style)
794 switch (style)
796 case Trace_Cap:
797 case Round_Cap:
798 gc->cap = GDK_CAP_ROUND;
799 gc->join = GDK_JOIN_ROUND;
800 break;
801 case Square_Cap:
802 case Beveled_Cap:
803 gc->cap = GDK_CAP_PROJECTING;
804 gc->join = GDK_JOIN_MITER;
805 break;
807 if (gc->gc)
808 gdk_gc_set_line_attributes (WHICH_GC (gc),
809 Vz (gc->width), GDK_LINE_SOLID,
810 gc->cap, gc->join);
813 void
814 ghid_set_line_width (hidGC gc, int width)
817 gc->width = width;
818 if (gc->gc)
819 gdk_gc_set_line_attributes (WHICH_GC (gc),
820 Vz (gc->width), GDK_LINE_SOLID,
821 gc->cap, gc->join);
824 void
825 ghid_set_draw_xor (hidGC gc, int xor)
827 gc->xor = xor;
828 if (!gc->gc)
829 return;
830 gdk_gc_set_function (gc->gc, xor ? GDK_XOR : GDK_COPY);
831 ghid_set_color (gc, gc->colorname);
834 void
835 ghid_set_draw_faded (hidGC gc, int faded)
837 printf ("ghid_set_draw_faded(%p,%d) -- not implemented\n", gc, faded);
840 void
841 ghid_set_line_cap_angle (hidGC gc, int x1, int y1, int x2, int y2)
843 printf ("ghid_set_line_cap_angle() -- not implemented\n");
846 static int
847 use_gc (hidGC gc)
849 if (!gport->pixmap)
850 return 0;
851 if (!gc->gc)
853 gc->gc = gdk_gc_new (gport->top_window->window);
854 ghid_set_color (gc, gc->colorname);
855 ghid_set_line_width (gc, gc->width);
856 ghid_set_line_cap (gc, gc->cap);
857 ghid_set_draw_xor (gc, gc->xor);
859 if (gc->mask_seq != mask_seq)
861 if (mask_seq)
862 gdk_gc_set_clip_mask (gc->gc, gport->mask);
863 else
864 gdk_gc_set_clip_mask (gc->gc, NULL);
865 gc->mask_seq = mask_seq;
867 gport->u_gc = WHICH_GC (gc);
868 return 1;
871 void
872 ghid_draw_line (hidGC gc, int x1, int y1, int x2, int y2)
874 double dx1, dy1, dx2, dy2;
876 dx1 = Vx ((double)x1);
877 dy1 = Vy ((double)y1);
878 dx2 = Vx ((double)x2);
879 dy2 = Vy ((double)y2);
881 if (! ClipLine (0, 0, gport->width, gport->height,
882 &dx1, &dy1, &dx2, &dy2, gc->width / gport->zoom))
883 return;
885 USE_GC (gc);
886 gdk_draw_line (gport->drawable, gport->u_gc, dx1, dy1, dx2, dy2);
889 void
890 ghid_draw_arc (hidGC gc, int cx, int cy,
891 int xradius, int yradius, int start_angle, int delta_angle)
893 gint vrx, vry;
894 gint w, h, radius;
896 w = gport->width * gport->zoom;
897 h = gport->height * gport->zoom;
898 radius = (xradius > yradius) ? xradius : yradius;
899 if (SIDE_X (cx) < gport->view_x0 - radius
900 || SIDE_X (cx) > gport->view_x0 + w + radius
901 || SIDE_Y (cy) < gport->view_y0 - radius
902 || SIDE_Y (cy) > gport->view_y0 + h + radius)
903 return;
905 USE_GC (gc);
906 vrx = Vz (xradius);
907 vry = Vz (yradius);
910 /* make sure we fall in the -180 to +180 range */
911 start_angle = (start_angle + 360 + 180) % 360 - 180;
912 if (ghid_flip_x)
914 start_angle = 180 - start_angle;
915 delta_angle = - delta_angle;
917 if (ghid_flip_y)
919 start_angle = - start_angle;
920 delta_angle = - delta_angle;
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 ghid_fill_rect,
1558 ghid_calibrate,
1559 ghid_shift_is_pressed,
1560 ghid_control_is_pressed,
1561 ghid_get_coords,
1562 ghid_set_crosshair,
1563 ghid_add_timer,
1564 ghid_stop_timer,
1565 ghid_watch_file,
1566 ghid_unwatch_file,
1567 ghid_add_block_hook,
1568 ghid_stop_block_hook,
1570 ghid_log,
1571 ghid_logv,
1572 ghid_confirm_dialog,
1573 ghid_close_confirm_dialog,
1574 ghid_report_dialog,
1575 ghid_prompt_for,
1576 ghid_fileselect,
1577 ghid_attribute_dialog,
1578 ghid_show_item,
1579 ghid_beep,
1580 ghid_progress
1583 HID ghid_extents = {
1584 sizeof (HID),
1585 "ghid_extents",
1586 "used to calculate extents",
1587 1, /* gui */
1588 0, /* printer */
1589 0, /* exporter */
1590 0, /* poly before */
1591 1, /* poly after */
1592 0, /* poly dicer */
1594 0 /* ghid_get_export_options */ ,
1595 0 /* ghid_do_export */ ,
1596 0 /* ghid_parse_arguments */ ,
1598 0 /* ghid_invalidate_wh */ ,
1599 0 /* ghid_invalidate_lr */ ,
1600 0 /* ghid_invalidate_all */ ,
1601 0 /* ghid_set_layer */ ,
1602 0 /* ghid_make_gc */ ,
1603 0 /* ghid_destroy_gc */ ,
1604 ghid_extents_use_mask,
1605 0 /* ghid_set_color */ ,
1606 0 /* ghid_set_line_cap */ ,
1607 0 /* ghid_set_line_width */ ,
1608 0 /* ghid_set_draw_xor */ ,
1609 0 /* ghid_set_draw_faded */ ,
1610 0 /* ghid_set_line_cap_angle */ ,
1611 ghid_extents_draw_line,
1612 ghid_extents_draw_arc,
1613 ghid_extents_draw_rect,
1614 ghid_extents_fill_circle,
1615 ghid_extents_fill_polygon,
1616 ghid_extents_fill_rect,
1618 0 /* ghid_calibrate */ ,
1619 0 /* ghid_shift_is_pressed */ ,
1620 0 /* ghid_control_is_pressed */ ,
1621 0 /* ghid_get_coords */ ,
1622 0 /* ghid_set_crosshair */ ,
1623 0 /* ghid_add_timer */ ,
1624 0 /* ghid_stop_timer */ ,
1625 0 /* ghid_watch_file */ ,
1626 0 /* ghid_unwatch_file */ ,
1627 0 /* ghid_add_block_hook */ ,
1628 0 /* ghid_stop_block_hook */ ,
1630 0 /* ghid_log */ ,
1631 0 /* ghid_logv */ ,
1632 0 /* ghid_confirm_dialog */ ,
1633 0 /* ghid_close_confirm_dialog */ ,
1634 0 /* ghid_report_dialog */ ,
1635 0 /* ghid_prompt_for */ ,
1636 0 /* ghid_attribute_dialog */ ,
1637 0 /* ghid_show_item */ ,
1638 0 /* ghid_beep */ ,
1639 0 /* ghid_progress */
1642 /* ------------------------------------------------------------
1644 * Actions specific to the GTK HID follow from here
1649 /* ------------------------------------------------------------ */
1650 static const char about_syntax[] =
1651 "About()";
1653 static const char about_help[] =
1654 "Tell the user about this version of PCB.";
1656 /* %start-doc actions About
1658 This just pops up a dialog telling the user which version of
1659 @code{pcb} they're running.
1661 %end-doc */
1664 static int
1665 About (int argc, char **argv, int x, int y)
1667 ghid_dialog_about ();
1668 return 0;
1671 /* ------------------------------------------------------------ */
1672 static const char getxy_syntax[] =
1673 "GetXY()";
1675 static const char getxy_help[] =
1676 "Get a coordinate.";
1678 /* %start-doc actions GetXY
1680 Prompts the user for a coordinate, if one is not already selected.
1682 %end-doc */
1684 static int
1685 GetXY (int argc, char **argv, int x, int y)
1687 return 0;
1690 /* ---------------------------------------------------------------------- */
1692 static int PointCursor (int argc, char **argv, int x, int y)
1694 if (!ghidgui)
1695 return 0;
1697 if (argc > 0)
1698 ghid_point_cursor ();
1699 else
1700 ghid_mode_cursor (Settings.Mode);
1701 return 0;
1704 /* ---------------------------------------------------------------------- */
1706 static int
1707 RouteStylesChanged (int argc, char **argv, int x, int y)
1709 gint n;
1711 if (PCB && PCB->RouteStyle[0].Name)
1712 for (n = 0; n < NUM_STYLES; ++n)
1713 ghid_route_style_set_button_label ((&PCB->RouteStyle[n])->Name, n);
1714 return 0;
1717 /* ---------------------------------------------------------------------- */
1720 PCBChanged (int argc, char **argv, int x, int y)
1722 if (!ghidgui)
1723 return 0;
1725 ghid_window_set_name_label (PCB->Name);
1727 if (!gport->pixmap)
1728 return 0;
1729 RouteStylesChanged (0, NULL, 0, 0);
1730 ghid_port_ranges_scale (TRUE);
1731 ghid_port_ranges_pan (0, 0, FALSE);
1732 ghid_port_ranges_zoom (0);
1733 ghid_port_ranges_changed ();
1734 ghid_sync_with_new_layout ();
1735 return 0;
1738 /* ---------------------------------------------------------------------- */
1740 static int
1741 LayerGroupsChanged (int argc, char **argv, int x, int y)
1743 printf ("LayerGroupsChanged -- not implemented\n");
1744 return 0;
1747 /* ---------------------------------------------------------------------- */
1749 static int
1750 LibraryChanged (int argc, char **argv, int x, int y)
1752 ghid_library_window_show (&ghid_port, FALSE);
1753 return 0;
1756 /* ---------------------------------------------------------------------- */
1758 static int
1759 Command (int argc, char **argv, int x, int y)
1761 ghid_handle_user_command (TRUE);
1762 return 0;
1765 /* ---------------------------------------------------------------------- */
1767 static int
1768 Load (int argc, char **argv, int x, int y)
1770 char *function;
1771 char *name = NULL;
1773 static gchar *current_element_dir = NULL;
1774 static gchar *current_layout_dir = NULL;
1775 static gchar *current_netlist_dir = NULL;
1777 /* we've been given the file name */
1778 if (argc > 1)
1779 return hid_actionv ("LoadFrom", argc, argv);
1781 function = argc ? argv[0] : "Layout";
1783 if (strcasecmp (function, "Netlist") == 0)
1785 name = ghid_dialog_file_select_open (_("Load netlist file"),
1786 &current_netlist_dir,
1787 Settings.FilePath);
1789 else if (strcasecmp (function, "ElementToBuffer") == 0)
1791 name = ghid_dialog_file_select_open (_("Load element to buffer"),
1792 &current_element_dir,
1793 Settings.LibraryTree);
1795 else if (strcasecmp (function, "LayoutToBuffer") == 0)
1797 name = ghid_dialog_file_select_open (_("Load layout file to buffer"),
1798 &current_layout_dir,
1799 Settings.FilePath);
1801 else if (strcasecmp (function, "Layout") == 0)
1803 name = ghid_dialog_file_select_open (_("Load layout file"),
1804 &current_layout_dir,
1805 Settings.FilePath);
1808 if (name)
1810 if (Settings.verbose)
1811 fprintf (stderr, "%s: Calling LoadFrom(%s, %s)\n", __FUNCTION__,
1812 function, name);
1813 hid_actionl ("LoadFrom", function, name, NULL);
1814 g_free (name);
1817 return 0;
1821 /* ---------------------------------------------------------------------- */
1822 static const char save_syntax[] =
1823 "Save()\n"
1824 "Save(Layout|LayoutAs)\n"
1825 "Save(AllConnections|AllUnusedPins|ElementConnections)\n"
1826 "Save(PasteBuffer)";
1828 static const char save_help[] =
1829 "Save layout and/or element data to a user-selected file.";
1831 /* %start-doc actions Save
1833 This action is a GUI front-end to the core's @code{SaveTo} action
1834 (@pxref{SaveTo Action}). If you happen to pass a filename, like
1835 @code{SaveTo}, then @code{SaveTo} is called directly. Else, the
1836 user is prompted for a filename to save, and then @code{SaveTo} is
1837 called with that filename.
1839 %end-doc */
1841 static int
1842 Save (int argc, char **argv, int x, int y)
1844 char *function;
1845 char *name;
1846 char *prompt;
1848 static gchar *current_dir = NULL;
1850 if (argc > 1)
1851 return hid_actionv ("SaveTo", argc, argv);
1853 function = argc ? argv[0] : "Layout";
1855 if (strcasecmp (function, "Layout") == 0)
1856 if (PCB->Filename)
1857 return hid_actionl ("SaveTo", "Layout", PCB->Filename, NULL);
1859 if (strcasecmp (function, "PasteBuffer") == 0)
1860 prompt = _("Save element as");
1861 else
1862 prompt = _("Save layout as");
1864 name = ghid_dialog_file_select_save (prompt,
1865 &current_dir,
1866 PCB->Filename, Settings.FilePath);
1868 if (name)
1870 FILE *exist;
1871 exist = fopen (name, "r");
1872 if (exist)
1874 fclose (exist);
1875 if (ghid_dialog_confirm (_("File exists! Ok to overwrite?"), NULL, NULL))
1877 if (Settings.verbose)
1878 fprintf (stderr, "Overwriting %s\n", name);
1880 else
1882 g_free (name);
1883 return 1;
1887 if (Settings.verbose)
1888 fprintf (stderr, "%s: Calling SaveTo(%s, %s)\n",
1889 __FUNCTION__, function, name);
1891 if (strcasecmp (function, "PasteBuffer") == 0)
1892 hid_actionl ("PasteBuffer", "Save", name, NULL);
1893 else
1896 * if we got this far and the function is Layout, then
1897 * we really needed it to be a LayoutAs. Otherwise
1898 * ActionSaveTo() will ignore the new file name we
1899 * just obtained.
1901 if (strcasecmp (function, "Layout") == 0)
1902 hid_actionl ("SaveTo", "LayoutAs", name, NULL);
1903 else
1904 hid_actionl ("SaveTo", function, name, NULL);
1906 g_free (name);
1908 else
1910 return 1;
1913 return 0;
1916 /* ---------------------------------------------------------------------- */
1917 static const char swapsides_syntax[] =
1918 "SwapSides(|v|h|r)";
1920 static const char swapsides_help[] =
1921 "Swaps the side of the board you're looking at.";
1923 /* %start-doc actions SwapSides
1925 This action changes the way you view the board.
1927 @table @code
1929 @item v
1930 Flips the board over vertically (up/down).
1932 @item h
1933 Flips the board over horizontally (left/right), like flipping pages in
1934 a book.
1936 @item r
1937 Rotates the board 180 degrees without changing sides.
1939 @end table
1941 If no argument is given, the board isn't moved but the opposite side
1942 is shown.
1944 Normally, this action changes which pads and silk layer are drawn as
1945 true silk, and which are drawn as the "invisible" layer. It also
1946 determines which solder mask you see.
1948 As a special case, if the layer group for the side you're looking at
1949 is visible and currently active, and the layer group for the opposite
1950 is not visible (i.e. disabled), then this action will also swap which
1951 layer group is visible and active, effectively swapping the ``working
1952 side'' of the board.
1954 %end-doc */
1957 static int
1958 SwapSides (int argc, char **argv, int x, int y)
1960 gint flipd;
1961 int do_flip_x = 0;
1962 int do_flip_y = 0;
1963 int comp_group = GetLayerGroupNumberByNumber (max_layer + COMPONENT_LAYER);
1964 int solder_group = GetLayerGroupNumberByNumber (max_layer + SOLDER_LAYER);
1965 int active_group = GetLayerGroupNumberByNumber (LayerStack[0]);
1966 int comp_showing =
1967 PCB->Data->Layer[PCB->LayerGroups.Entries[comp_group][0]].On;
1968 int solder_showing =
1969 PCB->Data->Layer[PCB->LayerGroups.Entries[solder_group][0]].On;
1972 if (argc > 0)
1974 switch (argv[0][0]) {
1975 case 'h':
1976 case 'H':
1977 ghid_flip_x = ! ghid_flip_x;
1978 do_flip_x = 1;
1979 break;
1980 case 'v':
1981 case 'V':
1982 ghid_flip_y = ! ghid_flip_y;
1983 do_flip_y = 1;
1984 break;
1985 case 'r':
1986 case 'R':
1987 ghid_flip_x = ! ghid_flip_x;
1988 ghid_flip_y = ! ghid_flip_y;
1989 do_flip_x = 1;
1990 do_flip_y = 1;
1991 break;
1992 default:
1993 return 1;
1995 /* SwapSides will swap this */
1996 Settings.ShowSolderSide = (ghid_flip_x == ghid_flip_y);
1999 Settings.ShowSolderSide = !Settings.ShowSolderSide;
2000 if (Settings.ShowSolderSide)
2002 if (active_group == comp_group && comp_showing && !solder_showing)
2004 ChangeGroupVisibility (PCB->LayerGroups.Entries[comp_group][0], 0,
2006 ChangeGroupVisibility (PCB->LayerGroups.Entries[solder_group][0], 1,
2010 else
2012 if (active_group == solder_group && solder_showing && !comp_showing)
2014 ChangeGroupVisibility (PCB->LayerGroups.Entries[solder_group][0], 0,
2016 ChangeGroupVisibility (PCB->LayerGroups.Entries[comp_group][0], 1,
2021 /* Update coordinates so that the current location stays where it was on the
2022 other side; we need to do this since the actual flip center is the
2023 center of the board while the user expect the center would be the current
2024 location */
2025 if (do_flip_x)
2027 flipd = PCB->MaxWidth / 2 - gport->view_x;
2028 ghid_port_ranges_pan (2 * flipd, 0, TRUE);
2030 if (do_flip_y)
2032 flipd = PCB->MaxHeight / 2 - gport->view_y;
2033 ghid_port_ranges_pan (0, 2 * flipd, TRUE);
2036 ghid_invalidate_all ();
2037 return 0;
2040 /* ------------------------------------------------------------ */
2042 static const char print_syntax[] =
2043 "Print()";
2045 static const char print_help[] =
2046 "Print the layout.";
2048 /* %start-doc actions Print
2050 This will find the default printing HID, prompt the user for its
2051 options, and print the layout.
2053 %end-doc */
2055 static int
2056 Print (int argc, char **argv, int x, int y)
2058 HID **hids;
2059 int i;
2060 HID *printer = NULL;
2062 hids = hid_enumerate ();
2063 for (i = 0; hids[i]; i++)
2065 if (hids[i]->printer)
2066 printer = hids[i];
2069 if (printer == NULL)
2071 gui->log (_("Can't find a suitable printer HID"));
2072 return -1;
2075 /* check if layout is empty */
2076 if (!IsDataEmpty (PCB->Data))
2078 ghid_dialog_print (printer);
2080 else
2081 gui->log (_("Can't print empty layout"));
2083 return 0;
2087 /* ------------------------------------------------------------ */
2089 static HID_Attribute
2090 printer_calibrate_attrs[] = {
2091 {"Enter Values here:", "",
2092 HID_Label, 0, 0, {0, 0, 0}, 0, 0},
2093 {"x-calibration", "X scale for calibrating your printer",
2094 HID_Real, 0.5, 25, {0, 0, 1.00}, 0, 0},
2095 {"y-calibration", "Y scale for calibrating your printer",
2096 HID_Real, 0.5, 25, {0, 0, 1.00}, 0, 0}
2098 static HID_Attr_Val printer_calibrate_values[3];
2100 static const char printcalibrate_syntax[] =
2101 "PrintCalibrate()";
2103 static const char printcalibrate_help[] =
2104 "Calibrate the printer.";
2106 /* %start-doc actions PrintCalibrate
2108 This will print a calibration page, which you would measure and type
2109 the measurements in, so that future printouts will be more precise.
2111 %end-doc */
2113 static int
2114 PrintCalibrate (int argc, char **argv, int x, int y)
2116 HID *printer = hid_find_printer ();
2117 printer->calibrate (0.0, 0.0);
2119 if (gui->attribute_dialog (printer_calibrate_attrs, 3,
2120 printer_calibrate_values,
2121 "Printer Calibration Values",
2122 "Enter calibration values for your printer"))
2123 return 1;
2124 printer->calibrate (printer_calibrate_values[1].real_value,
2125 printer_calibrate_values[2].real_value);
2126 return 0;
2129 /* ------------------------------------------------------------ */
2131 static int
2132 Export (int argc, char **argv, int x, int y)
2135 /* check if layout is empty */
2136 if (!IsDataEmpty (PCB->Data))
2138 ghid_dialog_export ();
2140 else
2141 gui->log (_("Can't export empty layout"));
2143 return 0;
2146 /* ------------------------------------------------------------ */
2148 static int
2149 Benchmark (int argc, char **argv, int x, int y)
2151 int i = 0;
2152 time_t start, end;
2153 BoxType region;
2154 GdkDisplay *display;
2156 display = gdk_drawable_get_display (gport->drawable);
2158 region.X1 = 0;
2159 region.Y1 = 0;
2160 region.X2 = PCB->MaxWidth;
2161 region.Y2 = PCB->MaxHeight;
2163 gdk_display_sync (display);
2164 time (&start);
2167 hid_expose_callback (&ghid_hid, &region, 0);
2168 gdk_display_sync (display);
2169 time (&end);
2170 i++;
2172 while (end - start < 10);
2174 printf ("%g redraws per second\n", i / 10.0);
2176 return 0;
2179 /* ------------------------------------------------------------ */
2181 static const char center_syntax[] =
2182 "Center()\n";
2184 static const char center_help[] =
2185 "Moves the pointer to the center of the window.";
2187 /* %start-doc actions Center
2189 Move the pointer to the center of the window, but only if it's
2190 currently within the window already.
2192 %end-doc */
2194 static int
2195 Center(int argc, char **argv, int x, int y)
2197 int x0, y0, w2, h2, dx, dy;
2199 if (argc != 0)
2200 AFAIL (center);
2202 x = GRIDFIT_X (SIDE_X (x), PCB->Grid);
2203 y = GRIDFIT_Y (SIDE_Y (y), PCB->Grid);
2205 w2 = gport->view_width / 2;
2206 h2 = gport->view_height / 2;
2207 x0 = x - w2;
2208 y0 = y - h2;
2210 if (x0 < 0)
2212 x0 = 0;
2213 x = x0 + w2;
2216 if (y0 < 0)
2218 y0 = 0;
2219 y = y0 + w2;
2222 dx = (x0 - gport->view_x0) / gport->zoom ;
2223 dy = (y0 - gport->view_y0) / gport->zoom;
2224 gport->view_x0 = x0;
2225 gport->view_y0 = y0;
2228 ghid_pan_fixup ();
2230 /* Move the pointer to the center of the window, but only if it's
2231 currently within the window already. Watch out for edges,
2232 though. */
2234 #if GTK_CHECK_VERSION(2,8,0)
2236 GdkDisplay *display;
2237 GdkScreen *screen;
2238 gint cx, cy;
2240 display = gdk_display_get_default ();
2241 screen = gdk_display_get_default_screen (display);
2243 /* figure out where the pointer is and then move it from there by the specified delta */
2244 gdk_display_get_pointer (display, NULL, &cx, &cy, NULL);
2245 gdk_display_warp_pointer (display, screen, cx - dx, cy - dy);
2248 * Note that under X11, gdk_display_warp_pointer is just a wrapper around XWarpPointer, but
2249 * hopefully by avoiding the direct call to an X function we might still work under windows
2250 * and other non-X11 based gdk's
2253 #else
2254 # ifdef HAVE_GDK_GDKX_H
2257 Window w_src, w_dst;
2258 w_src = GDK_WINDOW_XID (gport->drawing_area->window);
2259 w_dst = w_src;
2261 /* don't warp with the auto drc - that creates auto-scroll chaos */
2262 if (TEST_FLAG (AUTODRCFLAG, PCB) && Settings.Mode == LINE_MODE
2263 && Crosshair.AttachedLine.State != STATE_FIRST)
2264 return 0;
2266 XWarpPointer (GDK_DRAWABLE_XDISPLAY (gport->drawing_area->window),
2267 w_src, w_dst,
2268 0, 0, 0, 0,
2269 Vx2 (x), Vy2 (y));
2271 /* XWarpPointer creates Motion events normally bound to
2272 * EventMoveCrosshair.
2273 * We don't do any updates when EventMoveCrosshair
2274 * is called the next time to prevent from rounding errors
2276 /* FIXME?
2277 * IgnoreMotionEvents = ignore;
2280 # endif
2281 #endif
2283 return 0;
2286 /* ------------------------------------------------------------ */
2287 static const char cursor_syntax[] =
2288 "Cursor(Type,DeltaUp,DeltaRight,Units)";
2290 static const char cursor_help[] =
2291 "Move the cursor.";
2293 /* %start-doc actions Cursor
2295 This action moves the mouse cursor. Unlike other actions which take
2296 coordinates, this action's coordinates are always relative to the
2297 user's view of the board. Thus, a positive @var{DeltaUp} may move the
2298 cursor towards the board origin if the board is inverted.
2300 Type is one of @samp{Pan} or @samp{Warp}. @samp{Pan} causes the
2301 viewport to move such that the crosshair is under the mouse cursor.
2302 @samp{Warp} causes the mouse cursor to move to be above the crosshair.
2304 @var{Units} can be one of the following:
2306 @table @samp
2308 @item mil
2309 @itemx mm
2310 The cursor is moved by that amount, in board units.
2312 @item grid
2313 The cursor is moved by that many grid points.
2315 @item view
2316 The values are percentages of the viewport's view. Thus, a pan of
2317 @samp{100} would scroll the viewport by exactly the width of the
2318 current view.
2320 @item board
2321 The values are percentages of the board size. Thus, a move of
2322 @samp{50,50} moves you halfway across the board.
2324 @end table
2326 %end-doc */
2328 static int
2329 CursorAction(int argc, char **argv, int x, int y)
2331 int pan_warp = HID_SC_DO_NOTHING;
2332 double dx, dy;
2333 double xu = 0.0, yu = 0.0;
2335 if (argc != 4)
2336 AFAIL (cursor);
2338 if (strcasecmp (argv[0], "pan") == 0)
2339 pan_warp = HID_SC_PAN_VIEWPORT;
2340 else if (strcasecmp (argv[0], "warp") == 0)
2341 pan_warp = HID_SC_WARP_POINTER;
2342 else
2343 AFAIL (cursor);
2345 dx = strtod (argv[1], 0);
2346 if (ghid_flip_x)
2347 dx = -dx;
2348 dy = strtod (argv[2], 0);
2349 if (!ghid_flip_y)
2350 dy = -dy;
2353 * xu and yu are the scale factors that we multiply dx and dy by to
2354 * come up with PCB internal units.
2356 if (strncasecmp (argv[3], "mm", 2) == 0)
2357 xu = yu = MM_TO_COOR;
2358 else if (strncasecmp (argv[3], "mil", 3) == 0)
2359 xu = yu = 100;
2360 else if (strncasecmp (argv[3], "grid", 4) == 0)
2361 xu = yu = PCB->Grid;
2362 else if (strncasecmp (argv[3], "view", 4) == 0)
2364 xu = gport->view_width / 100.0;
2365 yu = gport->view_height / 100.0;
2367 else if (strncasecmp (argv[3], "board", 4) == 0)
2369 xu = PCB->MaxWidth / 100.0;
2370 yu = PCB->MaxHeight / 100.0;
2373 EventMoveCrosshair (Crosshair.X+(int)(dx*xu), Crosshair.Y+(int)(dy*yu));
2374 gui->set_crosshair (Crosshair.X, Crosshair.Y, pan_warp);
2376 return 0;
2378 /* ------------------------------------------------------------ */
2380 static const char dowindows_syntax[] =
2381 "DoWindows(1|2|3|4)\n"
2382 "DoWindows(Layout|Library|Log|Netlist|Preferences)";
2384 static const char dowindows_help[] =
2385 "Open various GUI windows.";
2387 /* %start-doc actions DoWindows
2389 @table @code
2391 @item 1
2392 @itemx Layout
2393 Open the layout window. Since the layout window is always shown
2394 anyway, this has no effect.
2396 @item 2
2397 @itemx Library
2398 Open the library window.
2400 @item 3
2401 @itemx Log
2402 Open the log window.
2404 @item 4
2405 @itemx Netlist
2406 Open the netlist window.
2408 @item 5
2409 @itemx Preferences
2410 Open the preferences window.
2412 @end table
2414 %end-doc */
2416 static int
2417 DoWindows (int argc, char **argv, int x, int y)
2419 char *a = argc == 1 ? argv[0] : "";
2421 if (strcmp (a, "1") == 0 || strcasecmp (a, "Layout") == 0)
2424 else if (strcmp (a, "2") == 0 || strcasecmp (a, "Library") == 0)
2426 ghid_library_window_show (gport, TRUE);
2428 else if (strcmp (a, "3") == 0 || strcasecmp (a, "Log") == 0)
2430 ghid_log_window_show (TRUE);
2432 else if (strcmp (a, "4") == 0 || strcasecmp (a, "Netlist") == 0)
2434 ghid_netlist_window_show (gport, TRUE);
2436 else if (strcmp (a, "5") == 0 || strcasecmp (a, "Preferences") == 0)
2438 ghid_config_window_show ();
2440 else
2442 AFAIL (dowindows);
2445 return 0;
2448 /* ------------------------------------------------------------ */
2449 static const char setunits_syntax[] =
2450 "SetUnits(mm|mil)";
2452 static const char setunits_help[] =
2453 "Set the default measurement units.";
2455 /* %start-doc actions SetUnits
2457 @table @code
2459 @item mil
2460 Sets the display units to mils (1/1000 inch).
2462 @item mm
2463 Sets the display units to millimeters.
2465 @end table
2467 %end-doc */
2469 static int
2470 SetUnits (int argc, char **argv, int x, int y)
2472 if (argc == 0)
2473 return 0;
2474 if (strcmp (argv[0], "mil") == 0)
2475 Settings.grid_units_mm = 0;
2476 if (strcmp (argv[0], "mm") == 0)
2477 Settings.grid_units_mm = 1;
2479 ghid_config_handle_units_changed ();
2481 ghid_set_status_line_label ();
2483 /* FIXME ?
2484 * lesstif_sizes_reset ();
2485 * lesstif_styles_update_values ();
2487 return 0;
2490 /* ------------------------------------------------------------ */
2491 static const char popup_syntax[] =
2492 "Popup(MenuName, [Button])";
2494 static const char popup_help[] =
2495 "Bring up the popup menu specified by @code{MenuName}.\n"
2496 "If called by a mouse event then the mouse button number\n"
2497 "must be specified as the optional second argument.";
2499 /* %start-doc actions Popup
2501 This just pops up the specified menu. The menu must have been defined
2502 as a named subresource of the Popups resource in the menu resource
2503 file. If called as a response to a mouse button click, the mouse
2504 button number must be specified as the second argument.
2506 %end-doc */
2509 static int
2510 Popup (int argc, char **argv, int x, int y)
2512 GtkWidget *menu;
2513 char *element;
2514 guint button;
2516 if (argc != 1 && argc != 2)
2517 AFAIL (popup);
2519 if (argc == 1)
2520 button = 0;
2521 else
2522 button = atoi (argv[1]);
2524 if ( (element = (char *) malloc ( (strlen (argv[0]) + 2) * sizeof (char))) == NULL )
2526 fprintf (stderr, "Popup(): malloc failed\n");
2527 exit (1);
2530 sprintf (element, "/%s", argv[0]);
2531 printf ("Loading popup \"%s\". Button = %u\n", element, button);
2533 menu = gtk_ui_manager_get_widget (ghidgui->ui_manager, element);
2534 free (element);
2536 if (! GTK_IS_MENU (menu))
2538 Message ("The specified popup menu \"%s\" has not been defined.\n", argv[0]);
2539 return 1;
2541 else
2543 ghidgui->in_popup = TRUE;
2544 gtk_widget_grab_focus (ghid_port.drawing_area);
2545 gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 0,
2546 gtk_get_current_event_time());
2548 return 0;
2551 static int
2552 Busy (int argc, char **argv, int x, int y)
2554 ghid_watch_cursor ();
2555 return 0;
2558 HID_Action ghid_main_action_list[] = {
2559 {"About", 0, About, about_help, about_syntax},
2560 {"Benchmark", 0, Benchmark},
2561 {"Busy", 0, Busy},
2562 {"Center", "Click on a location to center", Center, center_help, center_syntax},
2563 {"Command", 0, Command},
2564 {"Cursor", 0, CursorAction, cursor_help, cursor_syntax},
2565 {"DoWindows", 0, DoWindows, dowindows_help, dowindows_syntax},
2566 {"Export", 0, Export},
2567 {"GetXY", "", GetXY, getxy_help, getxy_syntax},
2568 {"LayerGroupsChanged", 0, LayerGroupsChanged},
2569 {"LibraryChanged", 0, LibraryChanged},
2570 {"Load", 0, Load},
2571 {"PCBChanged", 0, PCBChanged},
2572 {"PointCursor", 0, PointCursor},
2573 {"Popup", 0, Popup, popup_help, popup_syntax},
2574 {"Print", 0, Print,
2575 print_help, print_syntax},
2576 {"PrintCalibrate", 0, PrintCalibrate,
2577 printcalibrate_help, printcalibrate_syntax},
2578 {"RouteStylesChanged", 0, RouteStylesChanged},
2579 {"Save", 0, Save, save_help, save_syntax},
2580 {"SetUnits", 0, SetUnits, setunits_help, setunits_syntax},
2581 {"SwapSides", 0, SwapSides, swapsides_help, swapsides_syntax},
2582 {"Zoom", "Click on zoom focus", Zoom, zoom_help, zoom_syntax}
2585 REGISTER_ACTIONS (ghid_main_action_list)
2588 static int
2589 flag_flipx (int x)
2591 return ghid_flip_x;
2593 static int
2594 flag_flipy (int x)
2596 return ghid_flip_y;
2599 HID_Flag ghid_main_flag_list[] = {
2600 {"flip_x", flag_flipx, 0},
2601 {"flip_y", flag_flipy, 0}
2604 REGISTER_FLAGS (ghid_main_flag_list)
2606 #include "dolists.h"
2609 * We will need these for finding the windows installation
2610 * directory. Without that we can't find our fonts and
2611 * footprint libraries.
2613 #ifdef WIN32
2614 #include <windows.h>
2615 #include <winreg.h>
2616 #endif
2618 void
2619 hid_gtk_init ()
2621 #ifdef WIN32
2623 char * tmps;
2624 char * share_dir;
2626 tmps = g_win32_get_package_installation_directory (PACKAGE "-" VERSION, NULL);
2627 #define REST_OF_PATH G_DIR_SEPARATOR_S "share" G_DIR_SEPARATOR_S PACKAGE
2628 share_dir = (char *) malloc(strlen(tmps) +
2629 strlen(REST_OF_PATH) +
2631 sprintf (share_dir, "%s%s", tmps, REST_OF_PATH);
2632 free (tmps);
2633 #undef REST_OF_PATH
2634 printf ("\"Share\" installation path is \"%s\"\n", share_dir);
2635 #endif
2637 hid_register_hid (&ghid_hid);
2638 apply_default_hid (&ghid_extents, &ghid_hid);
2639 #include "gtk_lists.h"