pcb 4.1.1
An interactive printed circuit board layout editor.
|
00001 #ifdef HAVE_CONFIG_H 00002 #include "config.h" 00003 #endif 00004 00005 #include <stdio.h> 00006 #include <stdlib.h> 00007 #ifdef HAVE_STRING_H 00008 #include <string.h> 00009 #endif 00010 #include <math.h> 00011 #include <time.h> 00012 00013 00014 #include "action.h" 00015 #include "crosshair.h" 00016 #include "error.h" 00017 #include "../hidint.h" 00018 #include "gui.h" 00019 #include "hid/common/hidnogui.h" 00020 #include "hid/common/draw_helpers.h" 00021 #include "pcb-printf.h" 00022 00023 #ifdef HAVE_LIBDMALLOC 00024 #include <dmalloc.h> 00025 #endif 00026 00027 static void 00028 pan_common (GHidPort *port) 00029 { 00030 /* Don't pan so far the board is completely off the screen */ 00031 port->view.x0 = MAX (-port->view.width, port->view.x0); 00032 port->view.y0 = MAX (-port->view.height, port->view.y0); 00033 port->view.x0 = MIN ( port->view.x0, PCB->MaxWidth); 00034 port->view.y0 = MIN ( port->view.y0, PCB->MaxHeight); 00035 00036 ghidgui->adjustment_changed_holdoff = TRUE; 00037 gtk_range_set_value (GTK_RANGE (ghidgui->h_range), port->view.x0); 00038 gtk_range_set_value (GTK_RANGE (ghidgui->v_range), port->view.y0); 00039 ghidgui->adjustment_changed_holdoff = FALSE; 00040 00041 ghid_port_ranges_changed(); 00042 } 00043 00044 static void 00045 ghid_pan_view_abs (Coord pcb_x, Coord pcb_y, int widget_x, int widget_y) 00046 { 00047 gport->view.x0 = SIDE_X (pcb_x) - widget_x * gport->view.coord_per_px; 00048 gport->view.y0 = SIDE_Y (pcb_y) - widget_y * gport->view.coord_per_px; 00049 00050 pan_common (gport); 00051 } 00052 00053 void 00054 ghid_pan_view_rel (Coord dx, Coord dy) 00055 { 00056 gport->view.x0 += dx; 00057 gport->view.y0 += dy; 00058 00059 pan_common (gport); 00060 } 00061 00062 00063 /* gport->view.coord_per_px: 00064 * zoom value is PCB units per screen pixel. Larger numbers mean zooming 00065 * out - the largest value means you are looking at the whole board. 00066 * 00067 * gport->view_width and gport->view_height are in PCB coordinates 00068 */ 00069 00070 #define ALLOW_ZOOM_OUT_BY 10 /* Arbitrary, and same as the lesstif HID */ 00071 static void 00072 ghid_zoom_view_abs (Coord center_x, Coord center_y, double new_zoom) 00073 { 00074 double min_zoom, max_zoom; 00075 double xtmp, ytmp; 00076 00077 /* Limit the "minimum" zoom constant (maximum zoom), at 1 pixel per PCB 00078 * unit, and set the "maximum" zoom constant (minimum zoom), such that 00079 * the entire board just fits inside the viewport 00080 */ 00081 min_zoom = 1; 00082 max_zoom = MAX (PCB->MaxWidth / gport->width, 00083 PCB->MaxHeight / gport->height) * ALLOW_ZOOM_OUT_BY; 00084 new_zoom = MIN (MAX (min_zoom, new_zoom), max_zoom); 00085 00086 if (gport->view.coord_per_px == new_zoom) 00087 return; 00088 00089 xtmp = (SIDE_X (center_x) - gport->view.x0) / (double)gport->view.width; 00090 ytmp = (SIDE_Y (center_y) - gport->view.y0) / (double)gport->view.height; 00091 00092 gport->view.coord_per_px = new_zoom; 00093 pixel_slop = new_zoom; 00094 ghid_port_ranges_scale (); 00095 00096 gport->view.x0 = SIDE_X (center_x) - xtmp * gport->view.width; 00097 gport->view.y0 = SIDE_Y (center_y) - ytmp * gport->view.height; 00098 00099 pan_common (gport); 00100 00101 ghid_set_status_line_label (); 00102 } 00103 00104 static void 00105 ghid_zoom_view_rel (Coord center_x, Coord center_y, double factor) 00106 { 00107 ghid_zoom_view_abs (center_x, center_y, gport->view.coord_per_px * factor); 00108 } 00109 00110 static void 00111 ghid_zoom_view_fit (void) 00112 { 00113 ghid_pan_view_abs (SIDE_X (0), SIDE_Y (0), 0, 0); 00114 ghid_zoom_view_abs (SIDE_X (0), SIDE_Y (0), 00115 MAX (PCB->MaxWidth / gport->width, 00116 PCB->MaxHeight / gport->height)); 00117 } 00118 00119 static void 00120 ghid_flip_view (Coord center_x, Coord center_y, bool flip_x, bool flip_y) 00121 { 00122 int widget_x, widget_y; 00123 00124 /* Work out where on the screen the flip point is */ 00125 ghid_pcb_to_event_coords (center_x, center_y, &widget_x, &widget_y); 00126 00127 gport->view.flip_x = gport->view.flip_x != flip_x; 00128 gport->view.flip_y = gport->view.flip_y != flip_y; 00129 00130 /* Pan the board so the center location remains in the same place */ 00131 ghid_pan_view_abs (center_x, center_y, widget_x, widget_y); 00132 00133 ghid_invalidate_all (); 00134 } 00135 00136 /* ------------------------------------------------------------ */ 00137 00138 static const char zoom_syntax[] = 00139 "Zoom()\n" 00140 "Zoom(factor)"; 00141 00142 00143 static const char zoom_help[] = 00144 N_("Various zoom factor changes."); 00145 00146 /* %start-doc actions Zoom 00147 Changes the zoom (magnification) of the view of the board. If no 00148 arguments are passed, the view is scaled such that the board just fits 00149 inside the visible window (i.e. ``view all''). Otherwise, 00150 @var{factor} specifies a change in zoom factor. It may be prefixed by 00151 @code{+}, @code{-}, or @code{=} to change how the zoom factor is 00152 modified. The @var{factor} is a floating point number, such as 00153 @code{1.5} or @code{0.75}. 00154 00155 @table @code 00156 00157 @item +@var{factor} 00158 Values greater than 1.0 cause the board to be drawn smaller; more of 00159 the board will be visible. Values between 0.0 and 1.0 cause the board 00160 to be drawn bigger; less of the board will be visible. 00161 00162 @item -@var{factor} 00163 Values greater than 1.0 cause the board to be drawn bigger; less of 00164 the board will be visible. Values between 0.0 and 1.0 cause the board 00165 to be drawn smaller; more of the board will be visible. 00166 00167 @item =@var{factor} 00168 00169 The @var{factor} is an absolute zoom factor; the unit for this value 00170 is "PCB units per screen pixel". Since PCB units are 0.01 mil, a 00171 @var{factor} of 1000 means 10 mils (0.01 in) per pixel, or 100 DPI, 00172 about the actual resolution of most screens - resulting in an "actual 00173 size" board. Similarly, a @var{factor} of 100 gives you a 10x actual 00174 size. 00175 00176 @end table 00177 00178 Note that zoom factors of zero are silently ignored. 00179 00180 00181 00182 %end-doc */ 00183 00184 static int 00185 Zoom (int argc, char **argv, Coord x, Coord y) 00186 { 00187 const char *vp; 00188 double v; 00189 00190 if (argc > 1) 00191 AFAIL (zoom); 00192 00193 if (argc < 1) 00194 { 00195 ghid_zoom_view_fit (); 00196 return 0; 00197 } 00198 00199 vp = argv[0]; 00200 if (*vp == '+' || *vp == '-' || *vp == '=') 00201 vp++; 00202 v = g_ascii_strtod (vp, 0); 00203 if (v <= 0) 00204 return 1; 00205 switch (argv[0][0]) 00206 { 00207 case '-': 00208 ghid_zoom_view_rel (x, y, 1 / v); 00209 break; 00210 default: 00211 case '+': 00212 ghid_zoom_view_rel (x, y, v); 00213 break; 00214 case '=': 00215 ghid_zoom_view_abs (x, y, v); 00216 break; 00217 } 00218 00219 return 0; 00220 } 00221 00222 /* ------------------------------------------------------------ */ 00223 00224 void 00225 ghid_calibrate (double xval, double yval) 00226 { 00227 printf (_("ghid_calibrate() -- not implemented\n")); 00228 } 00229 00230 void 00231 ghid_notify_gui_is_up () 00232 { 00233 ghidgui->is_up = 1; 00234 } 00235 00236 int 00237 ghid_shift_is_pressed () 00238 { 00239 GdkModifierType mask; 00240 GHidPort *out = &ghid_port; 00241 00242 if (!ghidgui->is_up) 00243 return 0; 00244 00245 gdk_window_get_pointer (gtk_widget_get_window (out->drawing_area), 00246 NULL, NULL, &mask); 00247 return (mask & GDK_SHIFT_MASK) ? TRUE : FALSE; 00248 } 00249 00250 int 00251 ghid_control_is_pressed () 00252 { 00253 GdkModifierType mask; 00254 GHidPort *out = &ghid_port; 00255 00256 if (!ghidgui->is_up) 00257 return 0; 00258 00259 gdk_window_get_pointer (gtk_widget_get_window (out->drawing_area), 00260 NULL, NULL, &mask); 00261 return (mask & GDK_CONTROL_MASK) ? TRUE : FALSE; 00262 } 00263 00264 int 00265 ghid_mod1_is_pressed () 00266 { 00267 GdkModifierType mask; 00268 GHidPort *out = &ghid_port; 00269 00270 if (!ghidgui->is_up) 00271 return 0; 00272 00273 gdk_window_get_pointer (gtk_widget_get_window (out->drawing_area), 00274 NULL, NULL, &mask); 00275 #ifdef __APPLE__ 00276 return (mask & ( 1 << 13 ) ) ? TRUE : FALSE; // The option key is not MOD1, although it should be... 00277 #else 00278 return (mask & GDK_MOD1_MASK) ? TRUE : FALSE; 00279 #endif 00280 } 00281 00282 void 00283 ghid_set_crosshair (int x, int y, int action) 00284 { 00285 GdkDisplay *display; 00286 GdkScreen *screen; 00287 int offset_x, offset_y; 00288 int widget_x, widget_y; 00289 int pointer_x, pointer_y; 00290 Coord pcb_x, pcb_y; 00291 00292 if (gport->crosshair_x != x || gport->crosshair_y != y) 00293 { 00294 ghid_set_cursor_position_labels (); 00295 gport->crosshair_x = x; 00296 gport->crosshair_y = y; 00297 00298 /* FIXME - does this trigger the idle_proc stuff? It is in the 00299 * lesstif HID. Maybe something is needed here? 00300 * 00301 * need_idle_proc (); 00302 */ 00303 } 00304 00305 if (action != HID_SC_PAN_VIEWPORT && 00306 action != HID_SC_WARP_POINTER && 00307 action != HID_SC_CENTER_IN_VIEWPORT && 00308 action != HID_SC_CENTER_IN_VIEWPORT_AND_WARP_POINTER) 00309 return; 00310 00311 /* Find out where the drawing area is on the screen. gdk_display_get_pointer 00312 * and gdk_display_warp_pointer work relative to the whole display, whilst 00313 * our coordinates are relative to the drawing area origin. 00314 */ 00315 gdk_window_get_origin (gtk_widget_get_window (gport->drawing_area), 00316 &offset_x, &offset_y); 00317 00318 display = gdk_display_get_default (); 00319 screen = gdk_display_get_default_screen (display); 00320 00321 switch (action) { 00322 00323 case HID_SC_CENTER_IN_VIEWPORT: 00324 00325 // Center the viewport on the crosshair 00326 ghid_pan_view_abs (gport->crosshair_x - gport->view.width / 2, 00327 gport->crosshair_y - gport->view.height / 2, 00328 0, 0); 00329 00330 break; 00331 00332 case HID_SC_CENTER_IN_VIEWPORT_AND_WARP_POINTER: 00333 00334 // Center the viewport on the crosshair 00335 ghid_pan_view_abs (gport->crosshair_x - gport->view.width / 2, 00336 gport->crosshair_y - gport->view.height / 2, 00337 0, 0); 00338 00339 // We do this to make sure gdk has an up-to-date idea of the widget 00340 // coordinates so gdk_display_warp_pointer will go to the right spot. 00341 gdk_window_process_all_updates (); 00342 00343 // Warp pointer to crosshair 00344 ghid_pcb_to_event_coords (gport->crosshair_x, gport->crosshair_y, 00345 &widget_x, &widget_y); 00346 gdk_display_warp_pointer (display, screen, widget_x + offset_x, 00347 widget_y + offset_y); 00348 00349 break; 00350 00351 case HID_SC_PAN_VIEWPORT: 00352 /* Pan the board in the viewport so that the crosshair (who's location 00353 * relative on the board was set above) lands where the pointer is. 00354 * We pass the request to pan a particular point on the board to a 00355 * given widget coordinate of the viewport into the rendering code 00356 */ 00357 00358 /* Find out where the pointer is relative to the display */ 00359 gdk_display_get_pointer (display, NULL, &pointer_x, &pointer_y, NULL); 00360 00361 widget_x = pointer_x - offset_x; 00362 widget_y = pointer_y - offset_y; 00363 00364 ghid_event_to_pcb_coords (widget_x, widget_y, &pcb_x, &pcb_y); 00365 ghid_pan_view_abs (pcb_x, pcb_y, widget_x, widget_y); 00366 00367 /* Just in case we couldn't pan the board the whole way, 00368 * we warp the pointer to where the crosshair DID land. 00369 */ 00370 /* Fall through */ 00371 00372 case HID_SC_WARP_POINTER: 00373 screen = gdk_display_get_default_screen (display); 00374 00375 ghid_pcb_to_event_coords (x, y, &widget_x, &widget_y); 00376 00377 pointer_x = offset_x + widget_x; 00378 pointer_y = offset_y + widget_y; 00379 00380 gdk_display_warp_pointer (display, screen, pointer_x, pointer_y); 00381 00382 break; 00383 } 00384 } 00385 00386 typedef struct 00387 { 00388 void (*func) (hidval); 00389 guint id; 00390 hidval user_data; 00391 } 00392 GuiTimer; 00393 00394 /* We need a wrapper around the hid timer because a gtk timer needs 00395 | to return FALSE else the timer will be restarted. 00396 */ 00397 static gboolean 00398 ghid_timer (GuiTimer * timer) 00399 { 00400 (*timer->func) (timer->user_data); 00401 ghid_mode_cursor (Settings.Mode); 00402 return FALSE; /* Turns timer off */ 00403 } 00404 00405 hidval 00406 ghid_add_timer (void (*func) (hidval user_data), 00407 unsigned long milliseconds, hidval user_data) 00408 { 00409 GuiTimer *timer = g_new0 (GuiTimer, 1); 00410 hidval ret; 00411 00412 timer->func = func; 00413 timer->user_data = user_data; 00414 timer->id = g_timeout_add (milliseconds, (GSourceFunc) ghid_timer, timer); 00415 ret.ptr = (void *) timer; 00416 return ret; 00417 } 00418 00419 void 00420 ghid_stop_timer (hidval timer) 00421 { 00422 void *ptr = timer.ptr; 00423 00424 g_source_remove (((GuiTimer *) ptr)->id); 00425 g_free( ptr ); 00426 } 00427 00428 typedef struct 00429 { 00430 void (*func) ( hidval, int, unsigned int, hidval ); 00431 hidval user_data; 00432 int fd; 00433 GIOChannel *channel; 00434 gint id; 00435 } 00436 GuiWatch; 00437 00438 /* We need a wrapper around the hid file watch to pass the correct flags 00439 */ 00440 static gboolean 00441 ghid_watch (GIOChannel *source, GIOCondition condition, gpointer data) 00442 { 00443 unsigned int pcb_condition = 0; 00444 hidval x; 00445 GuiWatch *watch = (GuiWatch*)data; 00446 00447 if (condition & G_IO_IN) 00448 pcb_condition |= PCB_WATCH_READABLE; 00449 if (condition & G_IO_OUT) 00450 pcb_condition |= PCB_WATCH_WRITABLE; 00451 if (condition & G_IO_ERR) 00452 pcb_condition |= PCB_WATCH_ERROR; 00453 if (condition & G_IO_HUP) 00454 pcb_condition |= PCB_WATCH_HANGUP; 00455 00456 x.ptr = (void *) watch; 00457 watch->func (x, watch->fd, pcb_condition, watch->user_data); 00458 ghid_mode_cursor (Settings.Mode); 00459 00460 return TRUE; /* Leave watch on */ 00461 } 00462 00463 hidval 00464 ghid_watch_file (int fd, unsigned int condition, void (*func) (hidval watch, int fd, unsigned int condition, hidval user_data), 00465 hidval user_data) 00466 { 00467 GuiWatch *watch = g_new0 (GuiWatch, 1); 00468 hidval ret; 00469 unsigned int glib_condition = 0; 00470 00471 if (condition & PCB_WATCH_READABLE) 00472 glib_condition |= G_IO_IN; 00473 if (condition & PCB_WATCH_WRITABLE) 00474 glib_condition |= G_IO_OUT; 00475 if (condition & PCB_WATCH_ERROR) 00476 glib_condition |= G_IO_ERR; 00477 if (condition & PCB_WATCH_HANGUP) 00478 glib_condition |= G_IO_HUP; 00479 00480 watch->func = func; 00481 watch->user_data = user_data; 00482 watch->fd = fd; 00483 watch->channel = g_io_channel_unix_new( fd ); 00484 watch->id = g_io_add_watch( watch->channel, (GIOCondition)glib_condition, ghid_watch, watch ); 00485 00486 ret.ptr = (void *) watch; 00487 return ret; 00488 } 00489 00490 void 00491 ghid_unwatch_file (hidval data) 00492 { 00493 GuiWatch *watch = (GuiWatch*)data.ptr; 00494 00495 g_io_channel_shutdown( watch->channel, TRUE, NULL ); 00496 g_io_channel_unref( watch->channel ); 00497 g_free( watch ); 00498 } 00499 00500 typedef struct 00501 { 00502 GSource source; 00503 void (*func) (hidval user_data); 00504 hidval user_data; 00505 } BlockHookSource; 00506 00507 static gboolean ghid_block_hook_prepare (GSource *source, 00508 gint *timeout); 00509 static gboolean ghid_block_hook_check (GSource *source); 00510 static gboolean ghid_block_hook_dispatch (GSource *source, 00511 GSourceFunc callback, 00512 gpointer user_data); 00513 00514 static GSourceFuncs ghid_block_hook_funcs = { 00515 ghid_block_hook_prepare, 00516 ghid_block_hook_check, 00517 ghid_block_hook_dispatch, 00518 NULL // No destroy notification 00519 }; 00520 00521 static gboolean 00522 ghid_block_hook_prepare (GSource *source, 00523 gint *timeout) 00524 { 00525 hidval data = ((BlockHookSource *)source)->user_data; 00526 ((BlockHookSource *)source)->func( data ); 00527 return FALSE; 00528 } 00529 00530 static gboolean 00531 ghid_block_hook_check (GSource *source) 00532 { 00533 return FALSE; 00534 } 00535 00536 static gboolean 00537 ghid_block_hook_dispatch (GSource *source, 00538 GSourceFunc callback, 00539 gpointer user_data) 00540 { 00541 return FALSE; 00542 } 00543 00544 static hidval 00545 ghid_add_block_hook (void (*func) (hidval data), 00546 hidval user_data) 00547 { 00548 hidval ret; 00549 BlockHookSource *source; 00550 00551 source = (BlockHookSource *)g_source_new (&ghid_block_hook_funcs, sizeof( BlockHookSource )); 00552 00553 source->func = func; 00554 source->user_data = user_data; 00555 00556 g_source_attach ((GSource *)source, NULL); 00557 00558 ret.ptr = (void *) source; 00559 return ret; 00560 } 00561 00562 static void 00563 ghid_stop_block_hook (hidval mlpoll) 00564 { 00565 GSource *source = (GSource *)mlpoll.ptr; 00566 g_source_destroy( source ); 00567 } 00568 00569 int 00570 ghid_confirm_dialog (char *msg, ...) 00571 { 00572 int rv = 0; 00573 va_list ap; 00574 char *cancelmsg = NULL, *okmsg = NULL; 00575 static gint x = -1, y = -1; 00576 GtkWidget *dialog; 00577 GHidPort *out = &ghid_port; 00578 00579 va_start (ap, msg); 00580 cancelmsg = va_arg (ap, char *); 00581 okmsg = va_arg (ap, char *); 00582 va_end (ap); 00583 00584 if (!cancelmsg) 00585 { 00586 cancelmsg = _("_Cancel"); 00587 okmsg = _("_OK"); 00588 } 00589 00590 dialog = gtk_message_dialog_new (GTK_WINDOW (out->top_window), 00591 (GtkDialogFlags) (GTK_DIALOG_MODAL | 00592 GTK_DIALOG_DESTROY_WITH_PARENT), 00593 GTK_MESSAGE_QUESTION, 00594 GTK_BUTTONS_NONE, 00595 "%s", msg); 00596 gtk_dialog_add_button (GTK_DIALOG (dialog), 00597 cancelmsg, GTK_RESPONSE_CANCEL); 00598 if (okmsg) 00599 { 00600 gtk_dialog_add_button (GTK_DIALOG (dialog), 00601 okmsg, GTK_RESPONSE_OK); 00602 } 00603 00604 if(x != -1) { 00605 gtk_window_move(GTK_WINDOW (dialog), x, y); 00606 } 00607 00608 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) 00609 rv = 1; 00610 00611 gtk_window_get_position(GTK_WINDOW (dialog), &x, &y); 00612 00613 gtk_widget_destroy (dialog); 00614 return rv; 00615 } 00616 00617 int 00618 ghid_close_confirm_dialog () 00619 { 00620 switch (ghid_dialog_close_confirm ()) 00621 { 00622 case GUI_DIALOG_CLOSE_CONFIRM_SAVE: 00623 { 00624 if (hid_actionl ("Save", NULL)) 00625 { /* Save failed */ 00626 return 0; /* Cancel */ 00627 } else { 00628 return 1; /* Close */ 00629 } 00630 } 00631 case GUI_DIALOG_CLOSE_CONFIRM_NOSAVE: 00632 { 00633 return 1; /* Close */ 00634 } 00635 case GUI_DIALOG_CLOSE_CONFIRM_CANCEL: 00636 default: 00637 { 00638 return 0; /* Cancel */ 00639 } 00640 } 00641 } 00642 00643 void 00644 ghid_report_dialog (char *title, char *msg) 00645 { 00646 ghid_dialog_report (title, msg); 00647 } 00648 00649 char * 00650 ghid_prompt_for (const char *msg, const char *default_string) 00651 { 00652 char *rv; 00653 00654 rv = ghid_dialog_input (msg, default_string); 00655 return rv; 00656 } 00657 00658 /* FIXME -- implement a proper file select dialog */ 00659 #ifdef FIXME 00660 char * 00661 ghid_fileselect (const char *title, const char *descr, 00662 char *default_file, char *default_ext, 00663 const char *history_tag, int flags) 00664 { 00665 char *rv; 00666 00667 rv = ghid_dialog_input (title, default_file); 00668 return rv; 00669 } 00670 #endif 00671 00672 void 00673 ghid_show_item (void *item) 00674 { 00675 ghid_pinout_window_show (&ghid_port, (ElementType *) item); 00676 } 00677 00678 void 00679 ghid_beep () 00680 { 00681 gdk_beep (); 00682 } 00683 00684 struct progress_dialog 00685 { 00686 GtkWidget *dialog; 00687 GtkWidget *message; 00688 GtkWidget *progress; 00689 gint response_id; 00690 GMainLoop *loop; 00691 gboolean destroyed; 00692 gboolean started; 00693 GTimer *timer; 00694 00695 gulong response_handler; 00696 gulong destroy_handler; 00697 gulong delete_handler; 00698 }; 00699 00700 static void 00701 run_response_handler (GtkDialog *dialog, 00702 gint response_id, 00703 gpointer data) 00704 { 00705 struct progress_dialog *pd = data; 00706 00707 pd->response_id = response_id; 00708 } 00709 00710 static gint 00711 run_delete_handler (GtkDialog *dialog, 00712 GdkEventAny *event, 00713 gpointer data) 00714 { 00715 struct progress_dialog *pd = data; 00716 00717 pd->response_id = GTK_RESPONSE_DELETE_EVENT; 00718 00719 return TRUE; /* Do not destroy */ 00720 } 00721 00722 static void 00723 run_destroy_handler (GtkDialog *dialog, gpointer data) 00724 { 00725 struct progress_dialog *pd = data; 00726 00727 pd->destroyed = TRUE; 00728 } 00729 00730 static struct progress_dialog * 00731 make_progress_dialog (void) 00732 { 00733 struct progress_dialog *pd; 00734 GtkWidget *content_area; 00735 GtkWidget *alignment; 00736 GtkWidget *vbox; 00737 00738 pd = g_new0 (struct progress_dialog, 1); 00739 pd->response_id = GTK_RESPONSE_NONE; 00740 00741 pd->dialog = gtk_dialog_new_with_buttons (_("Progress"), 00742 GTK_WINDOW (gport->top_window), 00743 /* Modal so nothing else can get events whilst 00744 the main mainloop isn't running */ 00745 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, 00746 GTK_STOCK_CANCEL, 00747 GTK_RESPONSE_CANCEL, 00748 NULL); 00749 00750 gtk_window_set_deletable (GTK_WINDOW (pd->dialog), FALSE); 00751 gtk_window_set_skip_pager_hint (GTK_WINDOW (pd->dialog), TRUE); 00752 gtk_window_set_skip_taskbar_hint (GTK_WINDOW (pd->dialog), TRUE); 00753 gtk_widget_set_size_request (pd->dialog, 300, -1); 00754 00755 pd->message = gtk_label_new (NULL); 00756 gtk_misc_set_alignment (GTK_MISC (pd->message), 0., 0.); 00757 00758 pd->progress = gtk_progress_bar_new (); 00759 gtk_widget_set_size_request (pd->progress, -1, 26); 00760 00761 vbox = gtk_vbox_new (false, 0); 00762 gtk_box_pack_start (GTK_BOX (vbox), pd->message, true, true, 8); 00763 gtk_box_pack_start (GTK_BOX (vbox), pd->progress, false, true, 8); 00764 00765 alignment = gtk_alignment_new (0., 0., 1., 1.); 00766 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 8, 8, 8, 8); 00767 gtk_container_add (GTK_CONTAINER (alignment), vbox); 00768 00769 content_area = gtk_dialog_get_content_area (GTK_DIALOG (pd->dialog)); 00770 gtk_box_pack_start (GTK_BOX (content_area), alignment, true, true, 0); 00771 00772 gtk_widget_show_all (alignment); 00773 00774 g_object_ref (pd->dialog); 00775 gtk_window_present (GTK_WINDOW (pd->dialog)); 00776 00777 pd->response_handler = 00778 g_signal_connect (pd->dialog, "response", 00779 G_CALLBACK (run_response_handler), pd); 00780 pd->delete_handler = 00781 g_signal_connect (pd->dialog, "delete-event", 00782 G_CALLBACK (run_delete_handler), pd); 00783 pd->destroy_handler = 00784 g_signal_connect (pd->dialog, "destroy", 00785 G_CALLBACK (run_destroy_handler), pd); 00786 00787 pd->loop = g_main_loop_new (NULL, FALSE); 00788 pd->timer = g_timer_new (); 00789 00790 return pd; 00791 } 00792 00793 static void 00794 destroy_progress_dialog (struct progress_dialog *pd) 00795 { 00796 if (pd == NULL) 00797 return; 00798 00799 if (!pd->destroyed) 00800 { 00801 g_signal_handler_disconnect (pd->dialog, pd->response_handler); 00802 g_signal_handler_disconnect (pd->dialog, pd->delete_handler); 00803 g_signal_handler_disconnect (pd->dialog, pd->destroy_handler); 00804 } 00805 00806 g_timer_destroy (pd->timer); 00807 g_object_unref (pd->dialog); 00808 g_main_loop_unref (pd->loop); 00809 00810 gtk_widget_destroy (pd->dialog); 00811 00812 pd->loop = NULL; 00813 g_free (pd); 00814 } 00815 00816 static void 00817 handle_progress_dialog_events (struct progress_dialog *pd) 00818 { 00819 GMainContext * context = g_main_loop_get_context (pd->loop); 00820 00821 /* Process events */ 00822 while (g_main_context_pending (context)) 00823 { 00824 g_main_context_iteration (context, FALSE); 00825 } 00826 } 00827 00828 #define MIN_TIME_SEPARATION (50./1000.) /* 50ms */ 00829 static int 00830 ghid_progress (int so_far, int total, const char *message) 00831 { 00832 static struct progress_dialog *pd = NULL; 00833 00834 /* If we are finished, destroy any dialog */ 00835 if (so_far == 0 && total == 0 && message == NULL) 00836 { 00837 destroy_progress_dialog (pd); 00838 pd = NULL; 00839 return 0; 00840 } 00841 00842 if (pd == NULL) 00843 pd = make_progress_dialog (); 00844 00845 /* We don't want to keep the underlying process too busy whilst we 00846 * process events. If we get called quickly after the last progress 00847 * update, wait a little bit before we respond - perhaps the next 00848 * time progress is reported. 00849 00850 * The exception here is that we always want to process the first 00851 * batch of events after having shown the dialog for the first time 00852 */ 00853 if (pd->started && g_timer_elapsed (pd->timer, NULL) < MIN_TIME_SEPARATION) 00854 return 0; 00855 00856 gtk_label_set_text (GTK_LABEL (pd->message), message); 00857 gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (pd->progress), 00858 (double)so_far / (double)total); 00859 00860 handle_progress_dialog_events (pd); 00861 g_timer_start (pd->timer); 00862 00863 pd->started = TRUE; 00864 00865 return (pd->response_id == GTK_RESPONSE_CANCEL || 00866 pd->response_id == GTK_RESPONSE_DELETE_EVENT) ? 1 : 0; 00867 } 00868 00869 /* ---------------------------------------------------------------------- */ 00870 00871 00872 typedef struct { 00873 GtkWidget *del; 00874 GtkWidget *w_name; 00875 GtkWidget *w_value; 00876 } AttrRow; 00877 00878 static AttrRow *attr_row = 0; 00879 static int attr_num_rows = 0; 00880 static int attr_max_rows = 0; 00881 static AttributeListType *attributes_list; 00882 static GtkWidget *attributes_dialog, *attr_table; 00883 00884 static void attributes_delete_callback (GtkWidget *w, void *v); 00885 00886 #define GA_RESPONSE_REVERT 1 00887 #define GA_RESPONSE_NEW 2 00888 00889 static void 00890 ghid_attr_set_table_size () 00891 { 00892 gtk_table_resize (GTK_TABLE (attr_table), attr_num_rows > 0 ? attr_num_rows : 1, 3); 00893 } 00894 00895 static void 00896 ghid_attributes_need_rows (int new_max) 00897 { 00898 if (attr_max_rows < new_max) 00899 { 00900 if (attr_row) 00901 attr_row = (AttrRow *) realloc (attr_row, new_max * sizeof(AttrRow)); 00902 else 00903 attr_row = (AttrRow *) malloc (new_max * sizeof(AttrRow)); 00904 } 00905 while (attr_max_rows < new_max) 00906 { 00907 /* add [attr_max_rows] */ 00908 attr_row[attr_max_rows].del = gtk_button_new_with_label (_("del")); 00909 gtk_table_attach (GTK_TABLE (attr_table), attr_row[attr_max_rows].del, 00910 0, 1, 00911 attr_max_rows, attr_max_rows+1, 00912 (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), 00913 GTK_FILL, 00914 0, 0); 00915 g_signal_connect (G_OBJECT (attr_row[attr_max_rows].del), "clicked", 00916 G_CALLBACK (attributes_delete_callback), GINT_TO_POINTER (attr_max_rows) ); 00917 00918 attr_row[attr_max_rows].w_name = gtk_entry_new (); 00919 gtk_table_attach (GTK_TABLE (attr_table), attr_row[attr_max_rows].w_name, 00920 1, 2, 00921 attr_max_rows, attr_max_rows+1, 00922 (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), 00923 GTK_FILL, 00924 0, 0); 00925 00926 attr_row[attr_max_rows].w_value = gtk_entry_new (); 00927 gtk_table_attach (GTK_TABLE (attr_table), attr_row[attr_max_rows].w_value, 00928 2, 3, 00929 attr_max_rows, attr_max_rows+1, 00930 (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), 00931 GTK_FILL, 00932 0, 0); 00933 00934 attr_max_rows ++; 00935 } 00936 00937 /* Manage any previously unused rows we now need to show. */ 00938 while (attr_num_rows < new_max) 00939 { 00940 /* manage attr_num_rows */ 00941 gtk_widget_show (attr_row[attr_num_rows].del); 00942 gtk_widget_show (attr_row[attr_num_rows].w_name); 00943 gtk_widget_show (attr_row[attr_num_rows].w_value); 00944 attr_num_rows ++; 00945 } 00946 } 00947 00948 static void 00949 ghid_attributes_revert () 00950 { 00951 int i; 00952 00953 ghid_attributes_need_rows (attributes_list->Number); 00954 00955 /* Unmanage any previously used rows we don't need. */ 00956 while (attr_num_rows > attributes_list->Number) 00957 { 00958 attr_num_rows --; 00959 gtk_widget_hide (attr_row[attr_num_rows].del); 00960 gtk_widget_hide (attr_row[attr_num_rows].w_name); 00961 gtk_widget_hide (attr_row[attr_num_rows].w_value); 00962 } 00963 00964 /* Fill in values */ 00965 for (i=0; i<attributes_list->Number; i++) 00966 { 00967 /* create row [i] */ 00968 gtk_entry_set_text (GTK_ENTRY (attr_row[i].w_name), attributes_list->List[i].name); 00969 gtk_entry_set_text (GTK_ENTRY (attr_row[i].w_value), attributes_list->List[i].value); 00970 #if 0 00971 #endif 00972 } 00973 ghid_attr_set_table_size (); 00974 } 00975 00976 static void 00977 attributes_delete_callback (GtkWidget *w, void *v) 00978 { 00979 int i, n; 00980 00981 n = GPOINTER_TO_INT (v); 00982 00983 for (i=n; i<attr_num_rows-1; i++) 00984 { 00985 gtk_entry_set_text (GTK_ENTRY (attr_row[i].w_name), 00986 gtk_entry_get_text (GTK_ENTRY (attr_row[i+1].w_name))); 00987 gtk_entry_set_text (GTK_ENTRY (attr_row[i].w_value), 00988 gtk_entry_get_text (GTK_ENTRY (attr_row[i+1].w_value))); 00989 } 00990 attr_num_rows --; 00991 00992 gtk_widget_hide (attr_row[attr_num_rows].del); 00993 gtk_widget_hide (attr_row[attr_num_rows].w_name); 00994 gtk_widget_hide (attr_row[attr_num_rows].w_value); 00995 00996 ghid_attr_set_table_size (); 00997 } 00998 00999 static void 01000 ghid_attributes (char *owner, AttributeListType *attrs) 01001 { 01002 GtkWidget *content_area; 01003 int response; 01004 01005 attributes_list = attrs; 01006 01007 attr_max_rows = 0; 01008 attr_num_rows = 0; 01009 01010 attributes_dialog = gtk_dialog_new_with_buttons (owner, 01011 GTK_WINDOW (ghid_port.top_window), 01012 GTK_DIALOG_MODAL, 01013 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, 01014 _("Revert"), GA_RESPONSE_REVERT, 01015 _("New"), GA_RESPONSE_NEW, 01016 GTK_STOCK_OK, GTK_RESPONSE_OK, NULL); 01017 01018 attr_table = gtk_table_new (attrs->Number, 3, 0); 01019 01020 content_area = gtk_dialog_get_content_area (GTK_DIALOG (attributes_dialog)); 01021 gtk_box_pack_start (GTK_BOX (content_area), attr_table, FALSE, FALSE, 0); 01022 01023 gtk_widget_show (attr_table); 01024 01025 ghid_attributes_revert (); 01026 01027 while (1) 01028 { 01029 response = gtk_dialog_run (GTK_DIALOG (attributes_dialog)); 01030 01031 if (response == GTK_RESPONSE_CANCEL) 01032 break; 01033 01034 if (response == GTK_RESPONSE_OK) 01035 { 01036 int i; 01037 /* Copy the values back */ 01038 for (i=0; i<attributes_list->Number; i++) 01039 { 01040 if (attributes_list->List[i].name) 01041 free (attributes_list->List[i].name); 01042 if (attributes_list->List[i].value) 01043 free (attributes_list->List[i].value); 01044 } 01045 if (attributes_list->Max < attr_num_rows) 01046 { 01047 int sz = attr_num_rows * sizeof (AttributeType); 01048 if (attributes_list->List == NULL) 01049 attributes_list->List = (AttributeType *) malloc (sz); 01050 else 01051 attributes_list->List = (AttributeType *) realloc (attributes_list->List, sz); 01052 attributes_list->Max = attr_num_rows; 01053 } 01054 for (i=0; i<attr_num_rows; i++) 01055 { 01056 attributes_list->List[i].name = strdup (gtk_entry_get_text (GTK_ENTRY (attr_row[i].w_name))); 01057 attributes_list->List[i].value = strdup (gtk_entry_get_text (GTK_ENTRY (attr_row[i].w_value))); 01058 attributes_list->Number = attr_num_rows; 01059 } 01060 01061 break; 01062 } 01063 01064 if (response == GA_RESPONSE_REVERT) 01065 { 01066 /* Revert */ 01067 ghid_attributes_revert (); 01068 } 01069 01070 if (response == GA_RESPONSE_NEW) 01071 { 01072 ghid_attributes_need_rows (attr_num_rows + 1); /* also bumps attr_num_rows */ 01073 01074 gtk_entry_set_text (GTK_ENTRY (attr_row[attr_num_rows-1].w_name), ""); 01075 gtk_entry_set_text (GTK_ENTRY (attr_row[attr_num_rows-1].w_value), ""); 01076 01077 ghid_attr_set_table_size (); 01078 } 01079 } 01080 01081 gtk_widget_destroy (attributes_dialog); 01082 free (attr_row); 01083 attr_row = NULL; 01084 } 01085 01086 /* ---------------------------------------------------------------------- */ 01087 01088 HID_DRC_GUI ghid_drc_gui = { 01089 1, /* log_drc_overview */ 01090 0, /* log_drc_details */ 01091 ghid_drc_window_reset_message, 01092 ghid_drc_window_append_violation, 01093 ghid_drc_window_throw_dialog, 01094 }; 01095 01096 extern HID_Attribute *ghid_get_export_options (int *); 01097 01098 01099 /* ------------------------------------------------------------ 01100 * 01101 * Actions specific to the GTK HID follow from here 01102 * 01103 */ 01104 01105 01106 /* ------------------------------------------------------------ */ 01107 static const char about_syntax[] = 01108 "About()"; 01109 01110 static const char about_help[] = 01111 N_("Tell the user about this version of PCB."); 01112 01113 /* %start-doc actions About 01114 01115 This just pops up an about dialog telling the user which version of 01116 @code{pcb} they're running. 01117 01118 %end-doc */ 01119 01120 01121 static int 01122 About (int argc, char **argv, Coord x, Coord y) 01123 { 01124 ghid_dialog_about (); 01125 return 0; 01126 } 01127 01128 /* ------------------------------------------------------------ */ 01129 static const char getxy_syntax[] = 01130 "GetXY()"; 01131 01132 static const char getxy_help[] = 01133 N_("Get a coordinate."); 01134 01163 /* %start-doc actions GetXY 01164 01165 Prompts the user for a coordinate, if one is not already selected. 01166 01167 %end-doc */ 01168 01169 static int 01170 GetXY (int argc, char **argv, Coord x, Coord y) 01171 { 01172 gui->get_coords (argv[0], &x, &y); 01173 01174 return 0; 01175 } 01176 01177 /* ---------------------------------------------------------------------- */ 01178 01179 static int PointCursor (int argc, char **argv, Coord x, Coord y) 01180 { 01181 if (!ghidgui) 01182 return 0; 01183 01184 if (argc > 0) 01185 ghid_point_cursor (); 01186 else 01187 ghid_mode_cursor (Settings.Mode); 01188 return 0; 01189 } 01190 01191 /* ---------------------------------------------------------------------- */ 01192 01193 static int 01194 RouteStylesChanged (int argc, char **argv, Coord x, Coord y) 01195 { 01196 if (!ghidgui || !ghidgui->route_style_selector) 01197 return 0; 01198 01199 ghid_route_style_selector_sync 01200 (GHID_ROUTE_STYLE_SELECTOR (ghidgui->route_style_selector), 01201 Settings.LineThickness, Settings.ViaDrillingHole, 01202 Settings.ViaThickness, Settings.Keepaway); 01203 01204 return 0; 01205 } 01206 01207 /* ---------------------------------------------------------------------- */ 01208 01209 int 01210 PCBChanged (int argc, char **argv, Coord x, Coord y) 01211 { 01212 if (!ghidgui) 01213 return 0; 01214 01215 ghid_window_set_name_label (PCB->Name); 01216 01217 if (!gport->pixmap) 01218 return 0; 01219 01220 if (ghidgui->route_style_selector) 01221 { 01222 ghid_route_style_selector_empty 01223 (GHID_ROUTE_STYLE_SELECTOR (ghidgui->route_style_selector)); 01224 make_route_style_buttons 01225 (GHID_ROUTE_STYLE_SELECTOR (ghidgui->route_style_selector)); 01226 } 01227 RouteStylesChanged (0, NULL, 0, 0); 01228 01229 ghid_port_ranges_scale (); 01230 ghid_zoom_view_fit (); 01231 ghid_sync_with_new_layout (); 01232 crosshair_update_range(); 01233 return 0; 01234 } 01235 01236 /* ---------------------------------------------------------------------- */ 01237 01238 static int 01239 LayerGroupsChanged (int argc, char **argv, Coord x, Coord y) 01240 { 01241 printf (_("LayerGroupsChanged -- not implemented\n")); 01242 return 0; 01243 } 01244 01245 /* ---------------------------------------------------------------------- */ 01246 01247 static int 01248 LibraryChanged (int argc, char **argv, Coord x, Coord y) 01249 { 01250 /* No need to show the library window every time it changes... 01251 * ghid_library_window_show (&ghid_port, FALSE); 01252 */ 01253 return 0; 01254 } 01255 01256 /* ---------------------------------------------------------------------- */ 01257 01258 static const char command_syntax[] = 01259 "Command()"; 01260 01261 static const char command_help[] = 01262 "Displays the command line input window."; 01263 01264 /* %start-doc actions Command 01265 01266 The command window allows the user to manually enter actions to be 01267 executed. 01268 Action syntax can be done one of two ways: 01269 01270 @itemize @bullet 01271 01272 @item 01273 Follow the action name by an open parenthesis, arguments separated by 01274 commas, end with a close parenthesis. 01275 Example: 01276 01277 @example 01278 @code{Abc(1,2,3)} 01279 @end example 01280 01281 @item 01282 Separate the action name and arguments by spaces. 01283 Example: 01284 01285 @example 01286 @code{Abc 1 2 3} 01287 @end example 01288 01289 @end itemize 01290 01291 The first option allows you to have arguments with spaces in them, 01292 but the second is more ``natural'' to type for most people. 01293 01294 Note that action names are not case sensitive, but arguments normally 01295 are. However, most actions will check for ``keywords'' in a case 01296 insensitive way. 01297 01298 @code{Esc} closes the command window if pressed while the command window has 01299 focus. If you press the @code{Esc} key, the window goes away without invoking 01300 anything, and the next time you bring up the command window it resumes 01301 entering the command you were entering before. 01302 01303 %end-doc */ 01304 01305 static int 01306 Command (int argc, char **argv, Coord x, Coord y) 01307 { 01308 ghid_handle_user_command (TRUE); 01309 return 0; 01310 } 01311 01312 /* ---------------------------------------------------------------------- */ 01313 01314 static const char load_syntax[] = 01315 "Load(Layout|LayoutToBuffer|ElementToBuffer|Netlist|Revert,filename)"; 01316 01317 static const char load_help[] = 01318 N_("Load layout data from a user-selected file."); 01319 01320 /* %start-doc actions Load 01321 01322 This action is invoked by typing Load() in the command 01323 entry dialog. 01324 This action is a GUI front-end to the core's @code{LoadFrom} 01325 action (@pxref{LoadFrom Action}). 01326 If you happen to pass a filename, like @code{LoadFrom}, then 01327 @code{LoadFrom} is called directly. 01328 Else this action opens a file chooser dialog window. 01329 The user is to select a filename to load, and then that layout 01330 file is loaded into pcb. 01331 01332 %end-doc */ 01333 01334 static int 01335 Load (int argc, char **argv, Coord x, Coord y) 01336 { 01337 char *function; 01338 char *name = NULL; 01339 01340 static gchar *current_element_dir = NULL; 01341 static gchar *current_layout_dir = NULL; 01342 static gchar *current_netlist_dir = NULL; 01343 01344 /* we've been given the file name */ 01345 if (argc > 1) 01346 return hid_actionv ("LoadFrom", argc, argv); 01347 01348 function = argc ? argv[0] : (char *)"Layout"; 01349 01350 if (strcasecmp (function, "Netlist") == 0) 01351 { 01352 name = ghid_dialog_file_select_open (_("Load netlist file"), 01353 ¤t_netlist_dir, 01354 Settings.FilePath); 01355 } 01356 else if (strcasecmp (function, "ElementToBuffer") == 0) 01357 { 01358 name = ghid_dialog_file_select_open (_("Load element to buffer"), 01359 ¤t_element_dir, 01360 Settings.LibraryTree); 01361 } 01362 else if (strcasecmp (function, "LayoutToBuffer") == 0) 01363 { 01364 name = ghid_dialog_file_select_open (_("Load layout file to buffer"), 01365 ¤t_layout_dir, 01366 Settings.FilePath); 01367 } 01368 else if (strcasecmp (function, "Layout") == 0) 01369 { 01370 name = ghid_dialog_file_select_open (_("Load layout file"), 01371 ¤t_layout_dir, 01372 Settings.FilePath); 01373 } 01374 01375 if (name) 01376 { 01377 if (Settings.verbose) 01378 fprintf (stderr, "%s: Calling LoadFrom(%s, %s)\n", __FUNCTION__, 01379 function, name); 01380 hid_actionl ("LoadFrom", function, name, NULL); 01381 g_free (name); 01382 } 01383 01384 return 0; 01385 } 01386 01387 01388 /* ---------------------------------------------------------------------- */ 01389 static const char save_syntax[] = 01390 "Save()\n" 01391 "Save(Layout|LayoutAs)\n" 01392 "Save(AllConnections|AllUnusedPins|ElementConnections)\n" 01393 "Save(PasteBuffer)"; 01394 01395 static const char save_help[] = 01396 N_("Save layout and/or element data to a user-selected file."); 01397 01398 /* %start-doc actions Save 01399 01400 This action is a GUI front-end to the core's @code{SaveTo} action 01401 (@pxref{SaveTo Action}). If you happen to pass a filename, like 01402 @code{SaveTo}, then @code{SaveTo} is called directly. Else, the 01403 user is prompted for a filename to save, and then @code{SaveTo} is 01404 called with that filename. 01405 01406 %end-doc */ 01407 01408 static int 01409 Save (int argc, char **argv, Coord x, Coord y) 01410 { 01411 char *function; 01412 char *name; 01413 char *prompt; 01414 01415 static gchar *current_dir = NULL; 01416 01417 if (argc > 1) 01418 return hid_actionv ("SaveTo", argc, argv); 01419 01420 function = argc ? argv[0] : (char *)"Layout"; 01421 01422 if (strcasecmp (function, "Layout") == 0) 01423 if (PCB->Filename) 01424 return hid_actionl ("SaveTo", "Layout", PCB->Filename, NULL); 01425 01426 if (strcasecmp (function, "PasteBuffer") == 0) 01427 prompt = _("Save element as"); 01428 else 01429 prompt = _("Save layout as"); 01430 01431 name = ghid_dialog_file_select_save (prompt, 01432 ¤t_dir, 01433 PCB->Filename, Settings.FilePath); 01434 01435 if (name) 01436 { 01437 if (Settings.verbose) 01438 fprintf (stderr, "%s: Calling SaveTo(%s, %s)\n", 01439 __FUNCTION__, function, name); 01440 01441 if (strcasecmp (function, "PasteBuffer") == 0) 01442 hid_actionl ("PasteBuffer", "Save", name, NULL); 01443 else 01444 { 01445 /* 01446 * if we got this far and the function is Layout, then 01447 * we really needed it to be a LayoutAs. Otherwise 01448 * ActionSaveTo() will ignore the new file name we 01449 * just obtained. 01450 */ 01451 if (strcasecmp (function, "Layout") == 0) 01452 hid_actionl ("SaveTo", "LayoutAs", name, NULL); 01453 else 01454 hid_actionl ("SaveTo", function, name, NULL); 01455 } 01456 g_free (name); 01457 } 01458 else 01459 { 01460 return 1; 01461 } 01462 01463 return 0; 01464 } 01465 01466 /* ---------------------------------------------------------------------- */ 01467 static const char swapsides_syntax[] = 01468 "SwapSides(|v|h|r)"; 01469 01470 static const char swapsides_help[] = 01471 N_("Swaps the side of the board you're looking at."); 01472 01473 /* %start-doc actions SwapSides 01474 01475 This action changes the way you view the board. 01476 01477 @table @code 01478 01479 @item v 01480 Flips the board over vertically (up/down). 01481 01482 @item h 01483 Flips the board over horizontally (left/right), like flipping pages in 01484 a book. 01485 01486 @item r 01487 Rotates the board 180 degrees without changing sides. 01488 01489 @end table 01490 01491 If no argument is given, the board isn't moved but the opposite side 01492 is shown. 01493 01494 Normally, this action changes which pads and silk layer are drawn as 01495 true silk, and which are drawn as the "invisible" layer. It also 01496 determines which solder mask you see. 01497 01498 As a special case, if the layer group for the side you're looking at 01499 is visible and currently active, and the layer group for the opposite 01500 is not visible (i.e. disabled), then this action will also swap which 01501 layer group is visible and active, effectively swapping the ``working 01502 side'' of the board. 01503 01504 %end-doc */ 01505 01506 01507 static int 01508 SwapSides (int argc, char **argv, Coord x, Coord y) 01509 { 01510 int active_group = GetLayerGroupNumberByNumber (LayerStack[0]); 01511 int top_group = GetLayerGroupNumberBySide (TOP_SIDE); 01512 int bottom_group = GetLayerGroupNumberBySide (BOTTOM_SIDE); 01513 bool top_on = LAYER_PTR (PCB->LayerGroups.Entries[top_group][0])->On; 01514 bool bottom_on = LAYER_PTR (PCB->LayerGroups.Entries[bottom_group][0])->On; 01515 01516 if (argc > 0) 01517 { 01518 switch (argv[0][0]) { 01519 case 'h': 01520 case 'H': 01521 ghid_flip_view (gport->pcb_x, gport->pcb_y, true, false); 01522 break; 01523 case 'v': 01524 case 'V': 01525 ghid_flip_view (gport->pcb_x, gport->pcb_y, false, true); 01526 break; 01527 case 'r': 01528 case 'R': 01529 ghid_flip_view (gport->pcb_x, gport->pcb_y, true, true); 01530 Settings.ShowBottomSide = !Settings.ShowBottomSide; /* Swapped back below */ 01531 break; 01532 default: 01533 return 1; 01534 } 01535 } 01536 01537 Settings.ShowBottomSide = !Settings.ShowBottomSide; 01538 01539 if ((active_group == top_group && top_on && !bottom_on) || 01540 (active_group == bottom_group && bottom_on && !top_on)) 01541 { 01542 bool new_bottom_vis = Settings.ShowBottomSide; 01543 01544 ChangeGroupVisibility (PCB->LayerGroups.Entries[top_group][0], 01545 !new_bottom_vis, !new_bottom_vis); 01546 ChangeGroupVisibility (PCB->LayerGroups.Entries[bottom_group][0], 01547 new_bottom_vis, new_bottom_vis); 01548 } 01549 01550 layer_process ( NULL, NULL, NULL, LAYER_BUTTON_SILK ); 01551 hid_action ("LayersChanged"); 01552 01553 return 0; 01554 } 01555 01556 /* ------------------------------------------------------------ */ 01557 01558 static const char print_syntax[] = 01559 "Print()"; 01560 01561 static const char print_help[] = 01562 N_("Print the layout."); 01563 01564 /* %start-doc actions Print 01565 01566 This will find the default printing HID, prompt the user for its 01567 options, and print the layout. 01568 01569 %end-doc */ 01570 01571 static int 01572 Print (int argc, char **argv, Coord x, Coord y) 01573 { 01574 HID **hids; 01575 int i; 01576 HID *printer = NULL; 01577 01578 hids = hid_enumerate (); 01579 for (i = 0; hids[i]; i++) 01580 { 01581 if (hids[i]->printer) 01582 printer = hids[i]; 01583 } 01584 01585 if (printer == NULL) 01586 { 01587 gui->log (_("Can't find a suitable printer HID\n")); 01588 return -1; 01589 } 01590 01591 /* check if layout is empty */ 01592 if (!IsDataEmpty (PCB->Data)) 01593 { 01594 ghid_dialog_print (printer); 01595 } 01596 else 01597 gui->log (_("Can't print empty layout\n")); 01598 01599 return 0; 01600 } 01601 01602 01603 /* ------------------------------------------------------------ */ 01604 01605 static HID_Attribute 01606 printer_calibrate_attrs[] = { 01607 {N_("Enter Values here:"), "", 01608 HID_Label, 0, 0, {0, 0, 0}, 0, 0}, 01609 {N_("x-calibration"), N_("X scale for calibrating your printer"), 01610 HID_Real, 0.5, 25, {0, 0, 1.00}, 0, 0}, 01611 {N_("y-calibration"), N_("Y scale for calibrating your printer"), 01612 HID_Real, 0.5, 25, {0, 0, 1.00}, 0, 0} 01613 }; 01614 static HID_Attr_Val printer_calibrate_values[3]; 01615 01616 static const char printcalibrate_syntax[] = 01617 "PrintCalibrate()"; 01618 01619 static const char printcalibrate_help[] = 01620 N_("Calibrate the printer."); 01621 01622 /* %start-doc actions PrintCalibrate 01623 01624 This will print a calibration page, which you would measure and type 01625 the measurements in, so that future printouts will be more precise. 01626 01627 %end-doc */ 01628 01629 static int 01630 PrintCalibrate (int argc, char **argv, Coord x, Coord y) 01631 { 01632 HID *printer = hid_find_printer (); 01633 printer->calibrate (0.0, 0.0); 01634 01635 if (gui->attribute_dialog (printer_calibrate_attrs, 3, 01636 printer_calibrate_values, 01637 _("Printer Calibration Values"), 01638 _("Enter calibration values for your printer"))) 01639 return 1; 01640 printer->calibrate (printer_calibrate_values[1].real_value, 01641 printer_calibrate_values[2].real_value); 01642 return 0; 01643 } 01644 01645 /* ------------------------------------------------------------ */ 01646 01647 static const char export_syntax[] = 01648 "Export()\n"; 01649 01650 static const char export_help[] = 01651 N_("Open the Export dialog window."); 01652 01653 /* %start-doc actions Export 01654 01655 This action is invoked by typing Export() in the command 01656 entry dialog. 01657 01658 @noindent This action opens the Export dialog window. 01659 01660 %end-doc */ 01661 01662 static int 01663 Export (int argc, char **argv, Coord x, Coord y) 01664 { 01665 01666 /* check if layout is empty */ 01667 if (!IsDataEmpty (PCB->Data)) 01668 { 01669 ghid_dialog_export (); 01670 } 01671 else 01672 gui->log (_("Can't export empty layout\n")); 01673 01674 return 0; 01675 } 01676 01677 /* ------------------------------------------------------------ */ 01678 01679 static const char benchmark_syntax[] = 01680 "Benchmark()\n"; 01681 01682 static const char benchmark_help[] = 01683 N_("Report the amount of redraws per second."); 01684 01685 /* %start-doc actions Benchmark 01686 01687 This action is invoked by typing Benchmark() in the command 01688 entry dialog. 01689 01690 @noindent This action reports the number of redraws per second on the command 01691 line interface. 01692 01693 %end-doc */ 01694 01695 static int 01696 Benchmark (int argc, char **argv, Coord x, Coord y) 01697 { 01698 int i = 0; 01699 time_t start, end; 01700 GdkDisplay *display; 01701 01702 display = gdk_drawable_get_display (gport->drawable); 01703 01704 gdk_display_sync (display); 01705 time (&start); 01706 do 01707 { 01708 ghid_invalidate_all (); 01709 gdk_window_process_updates (gtk_widget_get_window (gport->drawing_area), 01710 FALSE); 01711 time (&end); 01712 i++; 01713 } 01714 while (end - start < 10); 01715 01716 printf (_("%g redraws per second\n"), (double)i / (double)(end-start)); 01717 01718 return 0; 01719 } 01720 01721 /* ------------------------------------------------------------ */ 01722 01723 static const char center_syntax[] = 01724 "Center()\n"; 01725 01726 static const char center_help[] = 01727 N_("Moves the pointer to the center of the window."); 01728 01729 /* %start-doc actions Center 01730 01731 Move the pointer to the center of the window, but only if it's 01732 currently within the window already. 01733 01734 %end-doc */ 01735 01736 static int 01737 Center(int argc, char **argv, Coord pcb_x, Coord pcb_y) 01738 { 01739 GdkDisplay *display; 01740 GdkScreen *screen; 01741 int offset_x, offset_y; 01742 int widget_x, widget_y; 01743 int pointer_x, pointer_y; 01744 01745 if (argc != 0) 01746 AFAIL (center); 01747 01748 /* Aim to put the given x, y PCB coordinates in the center of the widget */ 01749 widget_x = gport->width / 2; 01750 widget_y = gport->height / 2; 01751 01752 ghid_pan_view_abs (pcb_x, pcb_y, widget_x, widget_y); 01753 01754 /* Now move the mouse pointer to the place where the board location 01755 * actually ended up. 01756 * 01757 * XXX: Should only do this if we confirm we are inside our window? 01758 */ 01759 01760 ghid_pcb_to_event_coords (pcb_x, pcb_y, &widget_x, &widget_y); 01761 gdk_window_get_origin (gtk_widget_get_window (gport->drawing_area), 01762 &offset_x, &offset_y); 01763 01764 pointer_x = offset_x + widget_x; 01765 pointer_y = offset_y + widget_y; 01766 01767 display = gdk_display_get_default (); 01768 screen = gdk_display_get_default_screen (display); 01769 gdk_display_warp_pointer (display, screen, pointer_x, pointer_y); 01770 01771 return 0; 01772 } 01773 01774 /* ------------------------------------------------------------ */ 01775 static const char cursor_syntax[] = 01776 "Cursor(Type,DeltaUp,DeltaRight,Units)"; 01777 01778 static const char cursor_help[] = 01779 N_("Move the cursor."); 01780 01781 /* %start-doc actions Cursor 01782 01783 This action moves the mouse cursor. Unlike other actions which take 01784 coordinates, this action's coordinates are always relative to the 01785 user's view of the board. Thus, a positive @var{DeltaUp} may move the 01786 cursor towards the board origin if the board is inverted. 01787 01788 Type is one of @samp{Pan} or @samp{Warp}. @samp{Pan} causes the 01789 viewport to move such that the crosshair is under the mouse cursor. 01790 @samp{Warp} causes the mouse cursor to move to be above the crosshair. 01791 01792 @var{Units} can be one of the following: 01793 01794 @table @samp 01795 01796 @item mil 01797 @itemx mm 01798 The cursor is moved by that amount, in board units. 01799 01800 @item grid 01801 The cursor is moved by that many grid points. 01802 01803 @item view 01804 The values are percentages of the viewport's view. Thus, a pan of 01805 @samp{100} would scroll the viewport by exactly the width of the 01806 current view. 01807 01808 @item board 01809 The values are percentages of the board size. Thus, a move of 01810 @samp{50,50} moves you halfway across the board. 01811 01812 @end table 01813 01814 %end-doc */ 01815 01816 static int 01817 CursorAction(int argc, char **argv, Coord x, Coord y) 01818 { 01819 UnitList extra_units_x = { 01820 { "grid", PCB->Grid, 0 }, 01821 { "view", gport->view.width, UNIT_PERCENT }, 01822 { "board", PCB->MaxWidth, UNIT_PERCENT }, 01823 { "", 0, 0 } 01824 }; 01825 UnitList extra_units_y = { 01826 { "grid", PCB->Grid, 0 }, 01827 { "view", gport->view.height, UNIT_PERCENT }, 01828 { "board", PCB->MaxHeight, UNIT_PERCENT }, 01829 { "", 0, 0 } 01830 }; 01831 int pan_warp = HID_SC_DO_NOTHING; 01832 double dx, dy; 01833 01834 if (argc != 4) 01835 AFAIL (cursor); 01836 01837 if (strcasecmp (argv[0], "pan") == 0) 01838 pan_warp = HID_SC_PAN_VIEWPORT; 01839 else if (strcasecmp (argv[0], "warp") == 0) 01840 pan_warp = HID_SC_WARP_POINTER; 01841 else 01842 AFAIL (cursor); 01843 01844 dx = GetValueEx (argv[1], argv[3], NULL, extra_units_x, ""); 01845 if (gport->view.flip_x) 01846 dx = -dx; 01847 dy = GetValueEx (argv[2], argv[3], NULL, extra_units_y, ""); 01848 if (!gport->view.flip_y) 01849 dy = -dy; 01850 01851 EventMoveCrosshair (Crosshair.X + dx, Crosshair.Y + dy); 01852 gui->set_crosshair (Crosshair.X, Crosshair.Y, pan_warp); 01853 01854 return 0; 01855 } 01856 /* ------------------------------------------------------------ */ 01857 01858 static const char dowindows_syntax[] = 01859 "DoWindows(1|2|3|4|5|6)\n" 01860 "DoWindows(Layout|Library|Log|Netlist|Preferences|DRC)"; 01861 01862 static const char dowindows_help[] = 01863 N_("Open various GUI windows."); 01864 01865 /* %start-doc actions DoWindows 01866 01867 @table @code 01868 01869 @item 1 01870 @itemx Layout 01871 Open the layout window. Since the layout window is always shown 01872 anyway, this has no effect. 01873 01874 @item 2 01875 @itemx Library 01876 Open the library window. 01877 01878 @item 3 01879 @itemx Log 01880 Open the log window. 01881 01882 @item 4 01883 @itemx Netlist 01884 Open the netlist window. 01885 01886 @item 5 01887 @itemx Preferences 01888 Open the preferences window. 01889 01890 @item 6 01891 @itemx DRC 01892 Open the DRC violations window. 01893 01894 @end table 01895 01896 %end-doc */ 01897 01898 static int 01899 DoWindows (int argc, char **argv, Coord x, Coord y) 01900 { 01901 char *a = argc == 1 ? argv[0] : (char *)""; 01902 01903 if (strcmp (a, "1") == 0 || strcasecmp (a, "Layout") == 0) 01904 { 01905 } 01906 else if (strcmp (a, "2") == 0 || strcasecmp (a, "Library") == 0) 01907 { 01908 ghid_library_window_show (gport, TRUE); 01909 } 01910 else if (strcmp (a, "3") == 0 || strcasecmp (a, "Log") == 0) 01911 { 01912 ghid_log_window_show (TRUE); 01913 } 01914 else if (strcmp (a, "4") == 0 || strcasecmp (a, "Netlist") == 0) 01915 { 01916 ghid_netlist_window_show (gport, TRUE); 01917 } 01918 else if (strcmp (a, "5") == 0 || strcasecmp (a, "Preferences") == 0) 01919 { 01920 ghid_config_window_show (); 01921 } 01922 else if (strcmp (a, "6") == 0 || strcasecmp (a, "DRC") == 0) 01923 { 01924 ghid_drc_window_show (TRUE); 01925 } 01926 else 01927 { 01928 AFAIL (dowindows); 01929 } 01930 01931 return 0; 01932 } 01933 01934 /* ------------------------------------------------------------ */ 01935 static const char setunits_syntax[] = 01936 "SetUnits(mm|mil)"; 01937 01938 static const char setunits_help[] = 01939 N_("Set the default measurement units."); 01940 01941 /* %start-doc actions SetUnits 01942 01943 @table @code 01944 01945 @item mil 01946 Sets the display units to mils (1/1000 inch). 01947 01948 @item mm 01949 Sets the display units to millimeters. 01950 01951 @end table 01952 01953 %end-doc */ 01954 01955 static int 01956 SetUnits (int argc, char **argv, Coord x, Coord y) 01957 { 01958 const Unit *new_unit; 01959 if (argc == 0) 01960 return 0; 01961 01962 new_unit = get_unit_struct (argv[0]); 01963 if (new_unit != NULL && new_unit->allow != NO_PRINT) 01964 { 01965 Settings.grid_unit = new_unit; 01966 Settings.increments = get_increments_struct (Settings.grid_unit->family); 01967 AttributePut (PCB, "PCB::grid::unit", argv[0]); 01968 } 01969 01970 ghid_config_handle_units_changed (); 01971 01972 ghid_set_status_line_label (); 01973 01974 /* FIXME ? 01975 * lesstif_sizes_reset (); 01976 * lesstif_styles_update_values (); 01977 */ 01978 return 0; 01979 } 01980 01981 /* ------------------------------------------------------------ */ 01982 static const char scroll_syntax[] = 01983 "Scroll(up|down|left|right, [div])"; 01984 01985 static const char scroll_help[] = 01986 N_("Scroll the viewport."); 01987 01988 /* % start-doc actions Scroll 01989 01990 @item up|down|left|right 01991 Specifies the direction to scroll 01992 01993 @item div 01994 Optional. Specifies how much to scroll by. The viewport is scrolled 01995 by 1/div of what is visible, so div = 1 scrolls a whole page. If not 01996 default is given, div=40. 01997 01998 %end-doc */ 01999 02000 static int 02001 ScrollAction (int argc, char **argv, Coord x, Coord y) 02002 { 02003 gdouble dx = 0.0, dy = 0.0; 02004 int div = 40; 02005 02006 if (!ghidgui) 02007 return 0; 02008 02009 if (argc != 1 && argc != 2) 02010 AFAIL (scroll); 02011 02012 if (argc == 2) 02013 div = atoi(argv[1]); 02014 02015 if (strcasecmp (argv[0], "up") == 0) 02016 dy = -gport->view.height / div; 02017 else if (strcasecmp (argv[0], "down") == 0) 02018 dy = gport->view.height / div; 02019 else if (strcasecmp (argv[0], "right") == 0) 02020 dx = gport->view.width / div; 02021 else if (strcasecmp (argv[0], "left") == 0) 02022 dx = -gport->view.width / div; 02023 else 02024 AFAIL (scroll); 02025 02026 ghid_pan_view_rel (dx, dy); 02027 02028 return 0; 02029 } 02030 02031 /* ------------------------------------------------------------ */ 02032 static const char pan_syntax[] = 02033 "Pan([thumb], Mode)"; 02034 02035 static const char pan_help[] = 02036 N_("Start or stop panning (Mode = 1 to start, 0 to stop)\n" 02037 "Optional thumb argument is ignored for now in gtk hid.\n"); 02038 02039 /* %start-doc actions Pan 02040 02041 Start or stop panning. To start call with Mode = 1, to stop call with 02042 Mode = 0. 02043 02044 %end-doc */ 02045 02046 static int 02047 PanAction (int argc, char **argv, Coord x, Coord y) 02048 { 02049 int mode; 02050 02051 if (!ghidgui) 02052 return 0; 02053 02054 if (argc != 1 && argc != 2) 02055 AFAIL (pan); 02056 02057 if (argc == 1) 02058 mode = atoi(argv[0]); 02059 else 02060 { 02061 mode = atoi(argv[1]); 02062 Message (_("The gtk gui currently ignores the optional first argument " 02063 "to the Pan action.\nFeel free to provide patches.\n")); 02064 } 02065 02066 gport->panning = mode; 02067 02068 return 0; 02069 } 02070 02071 /* ------------------------------------------------------------ */ 02072 static const char popup_syntax[] = 02073 "Popup(MenuName, [Button])"; 02074 02075 static const char popup_help[] = 02076 N_("Bring up the popup menu specified by @code{MenuName}.\n" 02077 "If called by a mouse event then the mouse button number\n" 02078 "must be specified as the optional second argument."); 02079 02080 /* %start-doc actions Popup 02081 02082 This just pops up the specified menu. The menu must have been defined 02083 as a named subresource of the Popups resource in the menu resource 02084 file. The second, optional (and ignored) argument represents the mouse 02085 button number which is triggering the popup. 02086 02087 %end-doc */ 02088 02089 02090 static int 02091 Popup (int argc, char **argv, Coord x, Coord y) 02092 { 02093 GtkMenu *menu; 02094 02095 if (argc != 1 && argc != 2) 02096 AFAIL (popup); 02097 02098 menu = ghid_main_menu_get_popup (GHID_MAIN_MENU (ghidgui->menu_bar), argv[0]); 02099 if (! GTK_IS_MENU (menu)) 02100 { 02101 Message (_("The specified popup menu \"%s\" has not been defined.\n"), argv[0]); 02102 return 1; 02103 } 02104 else 02105 { 02106 ghidgui->in_popup = TRUE; 02107 gtk_widget_grab_focus (ghid_port.drawing_area); 02108 gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0, 02109 gtk_get_current_event_time()); 02110 } 02111 return 0; 02112 } 02113 /* ------------------------------------------------------------ */ 02114 static const char importgui_syntax[] = 02115 "ImportGUI()"; 02116 02117 static const char importgui_help[] = 02118 N_("Asks user which schematics to import into PCB.\n"); 02119 02120 /* %start-doc actions ImportGUI 02121 02122 Asks user which schematics to import into PCB. 02123 02124 %end-doc */ 02125 02126 02127 static int 02128 ImportGUI (int argc, char **argv, Coord x, Coord y) 02129 { 02130 GSList *names = NULL; 02131 gchar *name = NULL; 02132 gchar sname[128]; 02133 static gchar *current_layout_dir = NULL; 02134 static int I_am_recursing = 0; 02135 int rv, nsources; 02136 02137 if (I_am_recursing) 02138 return 1; 02139 02140 02141 names = ghid_dialog_file_select_multiple (_("Load schematics"), 02142 ¤t_layout_dir, 02143 Settings.FilePath); 02144 02145 nsources = 0; 02146 while (names != NULL) 02147 { 02148 name = names->data; 02149 02150 #ifdef DEBUG 02151 printf("File selected = %s\n", name); 02152 #endif 02153 02154 snprintf (sname, sizeof (sname), "import::src%d", nsources); 02155 AttributePut (PCB, sname, name); 02156 02157 g_free (name); 02158 nsources++; 02159 names = g_slist_next (names); 02160 } 02161 g_slist_free (names); 02162 02163 I_am_recursing = 1; 02164 rv = hid_action ("Import"); 02165 I_am_recursing = 0; 02166 02167 return rv; 02168 } 02169 02170 /* ------------------------------------------------------------ */ 02171 02172 static const char busy_syntax[] = 02173 "Busy()\n"; 02174 02175 static const char busy_help[] = 02176 N_("Show a busy cursor."); 02177 02178 /* %start-doc actions Busy 02179 02180 This action is invoked by the program when there is a waiting state for 02181 the user. 02182 02183 @noindent This action shows a "watch" like cursor graphic to indicate 02184 the pcb program is chewing on a task taking significant time. 02185 02186 @noindent The cursor graphic is reset when the task is finished. 02187 02188 When invoked by the user from the command entry window (no program task 02189 running) the cursor graphic is reset when the user enters a coordinate 02190 (left mouse button click). 02191 02192 %end-doc */ 02193 02194 static int 02195 Busy (int argc, char **argv, Coord x, Coord y) 02196 { 02197 ghid_watch_cursor (); 02198 return 0; 02199 } 02200 02201 HID_Action ghid_main_action_list[] = { 02202 {"About", 0, About, about_help, about_syntax}, 02203 {"Benchmark", 0, Benchmark, benchmark_help, benchmark_syntax}, 02204 {"Busy", 0, Busy, busy_help, busy_syntax}, 02205 {"Center", N_("Click on a location to center"), Center, center_help, center_syntax}, 02206 {"Command", 0, Command, command_help, command_syntax}, 02207 {"Cursor", 0, CursorAction, cursor_help, cursor_syntax}, 02208 {"DoWindows", 0, DoWindows, dowindows_help, dowindows_syntax}, 02209 {"Export", 0, Export, export_help, export_syntax}, 02210 {"GetXY", 0, GetXY, getxy_help, getxy_syntax}, 02211 {"ImportGUI", 0, ImportGUI, importgui_help, importgui_syntax}, 02212 {"LayerGroupsChanged", 0, LayerGroupsChanged}, 02213 {"LibraryChanged", 0, LibraryChanged}, 02214 {"Load", 0, Load, load_help, load_syntax}, 02215 {"Pan", 0, PanAction, pan_help, pan_syntax}, 02216 {"PCBChanged", 0, PCBChanged}, 02217 {"PointCursor", 0, PointCursor}, 02218 {"Popup", 0, Popup, popup_help, popup_syntax}, 02219 {"Print", 0, Print, print_help, print_syntax}, 02220 {"PrintCalibrate", 0, PrintCalibrate, printcalibrate_help, printcalibrate_syntax}, 02221 {"RouteStylesChanged", 0, RouteStylesChanged}, 02222 {"Save", 0, Save, save_help, save_syntax}, 02223 {"Scroll", N_("Click on a place to scroll"), ScrollAction, scroll_help, scroll_syntax}, 02224 {"SetUnits", 0, SetUnits, setunits_help, setunits_syntax}, 02225 {"SwapSides", 0, SwapSides, swapsides_help, swapsides_syntax}, 02226 {"Zoom", N_("Click on zoom focus"), Zoom, zoom_help, zoom_syntax} 02227 }; 02228 02229 REGISTER_ACTIONS (ghid_main_action_list) 02230 02231 02232 static int 02233 flag_flipx (void *data) 02234 { 02235 return gport->view.flip_x; 02236 } 02237 02238 static int 02239 flag_flipy (void *data) 02240 { 02241 return gport->view.flip_y; 02242 } 02243 02244 HID_Flag ghid_main_flag_list[] = { 02245 {"flip_x", flag_flipx, NULL}, 02246 {"flip_y", flag_flipy, NULL} 02247 }; 02248 02249 REGISTER_FLAGS (ghid_main_flag_list) 02250 02251 #include "dolists.h" 02252 02253 /* 02254 * We will need these for finding the windows installation 02255 * directory. Without that we can't find our fonts and 02256 * footprint libraries. 02257 */ 02258 #ifdef WIN32 02259 #define WIN32_LEAN_AND_MEAN 02260 #include <windows.h> 02261 #include <winreg.h> 02262 #endif 02263 02264 HID ghid_hid; 02265 HID_DRAW ghid_graphics; 02266 02267 void 02268 hid_gtk_init () 02269 { 02270 #ifdef WIN32 02271 char * tmps; 02272 char * share_dir; 02273 char *loader_cache; 02274 size_t buffer_size; 02275 FILE *loader_file; 02276 #endif 02277 02278 #ifdef WIN32 02279 tmps = g_win32_get_package_installation_directory_of_module (NULL); 02280 #define REST_OF_PATH G_DIR_SEPARATOR_S "share" G_DIR_SEPARATOR_S PACKAGE 02281 #define REST_OF_CACHE G_DIR_SEPARATOR_S "loaders.cache" 02282 buffer_size = strlen (tmps) + strlen (REST_OF_PATH) + 1; 02283 share_dir = (char *)malloc (buffer_size); 02284 snprintf (share_dir, buffer_size, "%s%s", tmps, REST_OF_PATH); 02285 02286 /* Point to our gdk-pixbuf loader cache. */ 02287 buffer_size = strlen (bindir) + strlen (REST_OF_CACHE) + 1; 02288 loader_cache = (char *)malloc (buffer_size); 02289 snprintf (loader_cache, buffer_size, "%s%s", bindir, REST_OF_CACHE); 02290 loader_file = fopen (loader_cache, "r"); 02291 if (loader_file) 02292 { 02293 fclose (loader_file); 02294 g_setenv ("GDK_PIXBUF_MODULE_FILE", loader_cache, TRUE); 02295 } 02296 02297 free (tmps); 02298 #undef REST_OF_PATH 02299 printf ("\"Share\" installation path is \"%s\"\n", share_dir); 02300 free (share_dir); 02301 #endif 02302 02303 memset (&ghid_hid, 0, sizeof (HID)); 02304 memset (&ghid_graphics, 0, sizeof (HID_DRAW)); 02305 02306 common_nogui_init (&ghid_hid); 02307 common_draw_helpers_init (&ghid_graphics); 02308 02309 ghid_hid.struct_size = sizeof (HID); 02310 ghid_hid.name = "gtk"; 02311 ghid_hid.description = "Gtk - The Gimp Toolkit"; 02312 ghid_hid.gui = 1; 02313 ghid_hid.poly_after = 1; 02314 02315 ghid_hid.get_export_options = ghid_get_export_options; 02316 ghid_hid.do_export = ghid_do_export; 02317 ghid_hid.parse_arguments = ghid_parse_arguments; 02318 ghid_hid.invalidate_lr = ghid_invalidate_lr; 02319 ghid_hid.invalidate_all = ghid_invalidate_all; 02320 ghid_hid.notify_crosshair_change = ghid_notify_crosshair_change; 02321 ghid_hid.notify_mark_change = ghid_notify_mark_change; 02322 ghid_hid.set_layer = ghid_set_layer; 02323 02324 ghid_hid.calibrate = ghid_calibrate; 02325 ghid_hid.shift_is_pressed = ghid_shift_is_pressed; 02326 ghid_hid.control_is_pressed = ghid_control_is_pressed; 02327 ghid_hid.mod1_is_pressed = ghid_mod1_is_pressed, 02328 ghid_hid.get_coords = ghid_get_coords; 02329 ghid_hid.set_crosshair = ghid_set_crosshair; 02330 ghid_hid.add_timer = ghid_add_timer; 02331 ghid_hid.stop_timer = ghid_stop_timer; 02332 ghid_hid.watch_file = ghid_watch_file; 02333 ghid_hid.unwatch_file = ghid_unwatch_file; 02334 ghid_hid.add_block_hook = ghid_add_block_hook; 02335 ghid_hid.stop_block_hook = ghid_stop_block_hook; 02336 02337 ghid_hid.log = ghid_log; 02338 ghid_hid.logv = ghid_logv; 02339 ghid_hid.confirm_dialog = ghid_confirm_dialog; 02340 ghid_hid.close_confirm_dialog = ghid_close_confirm_dialog; 02341 ghid_hid.report_dialog = ghid_report_dialog; 02342 ghid_hid.prompt_for = ghid_prompt_for; 02343 ghid_hid.fileselect = ghid_fileselect; 02344 ghid_hid.attribute_dialog = ghid_attribute_dialog; 02345 ghid_hid.show_item = ghid_show_item; 02346 ghid_hid.beep = ghid_beep; 02347 ghid_hid.progress = ghid_progress; 02348 ghid_hid.drc_gui = &ghid_drc_gui, 02349 ghid_hid.edit_attributes = ghid_attributes; 02350 02351 ghid_hid.request_debug_draw = ghid_request_debug_draw; 02352 ghid_hid.flush_debug_draw = ghid_flush_debug_draw; 02353 ghid_hid.finish_debug_draw = ghid_finish_debug_draw; 02354 02355 ghid_hid.notify_save_pcb = ghid_notify_save_pcb; 02356 ghid_hid.notify_filename_changed = ghid_notify_filename_changed; 02357 02358 ghid_hid.graphics = &ghid_graphics; 02359 02360 ghid_graphics.make_gc = ghid_make_gc; 02361 ghid_graphics.destroy_gc = ghid_destroy_gc; 02362 ghid_graphics.use_mask = ghid_use_mask; 02363 ghid_graphics.set_color = ghid_set_color; 02364 ghid_graphics.set_line_cap = ghid_set_line_cap; 02365 ghid_graphics.set_line_width = ghid_set_line_width; 02366 ghid_graphics.set_draw_xor = ghid_set_draw_xor; 02367 ghid_graphics.draw_line = ghid_draw_line; 02368 ghid_graphics.draw_arc = ghid_draw_arc; 02369 ghid_graphics.draw_rect = ghid_draw_rect; 02370 ghid_graphics.fill_circle = ghid_fill_circle; 02371 ghid_graphics.fill_polygon = ghid_fill_polygon; 02372 ghid_graphics.fill_rect = ghid_fill_rect; 02373 02374 ghid_graphics.draw_grid = ghid_draw_grid; 02375 02376 ghid_graphics.draw_pcb_polygon = common_gui_draw_pcb_polygon; 02377 02378 hid_register_hid (&ghid_hid); 02379 #include "gtk_lists.h" 02380 }