/* --------------------------------------------------------------------------- * load PCB * parse the file with enabled 'PCB mode' (see parser) * if successful, update some other stuff * * If revert is true, we pass "revert" as a parameter * to the HID's PCBChanged action. */ static int real_load_pcb (char *Filename, bool revert) { const char *unit_suffix; char *new_filename; PCBTypePtr newPCB = CreateNewPCB_ (false); PCBTypePtr oldPCB; #ifdef DEBUG double elapsed; clock_t start, end; start = clock (); #endif resolve_path(Filename, &new_filename); oldPCB = PCB; PCB = newPCB; /* mark the default font invalid to know if the file has one */ newPCB->Font.Valid = false; /* new data isn't added to the undo list */ if (!ParsePCB (PCB, new_filename)) { RemovePCB (oldPCB); CreateNewPCBPost (PCB, 0); ResetStackAndVisibility (); /* update cursor location */ Crosshair.X = CLAMP (PCB->CursorX, 0, PCB->MaxWidth); Crosshair.Y = CLAMP (PCB->CursorY, 0, PCB->MaxHeight); /* update cursor confinement and output area (scrollbars) */ ChangePCBSize (PCB->MaxWidth, PCB->MaxHeight); /* enable default font if necessary */ if (!PCB->Font.Valid) { Message (_ ("File '%s' has no font information, using default font\n"), new_filename); PCB->Font.Valid = true; } /* clear 'changed flag' */ SetChangedFlag (false); PCB->Filename = new_filename; /* just in case a bad file saved file is loaded */ /* Use attribute PCB::grid::unit as unit, if we can */ unit_suffix = AttributeGet (PCB, "PCB::grid::unit"); if (unit_suffix && *unit_suffix) { const Unit *new_unit = get_unit_struct (unit_suffix); if (new_unit) Settings.grid_unit = new_unit; } AttributePut (PCB, "PCB::grid::unit", Settings.grid_unit->suffix); sort_netlist (); set_some_route_style (); if (revert) hid_actionl ("PCBChanged", "revert", NULL); else hid_action ("PCBChanged"); #ifdef DEBUG end = clock (); elapsed = ((double) (end - start)) / CLOCKS_PER_SEC; gui->log ("Loading file %s took %f seconds of CPU time\n", new_filename, elapsed); #endif return (0); } PCB = oldPCB; hid_action ("PCBChanged"); /* release unused memory */ RemovePCB (newPCB); return (1); }
static void nbcb_find (LibraryMenuType *net, int pos) { char *name = net->Name + 2; hid_actionl ("netlist", "find", name, NULL); }
/* --------------------------------------------------------------------------- * recalculates the passed coordinates to fit the current grid setting */ void FitCrosshairIntoGrid (LocationType X, LocationType Y) { LocationType x2, y2, x0, y0; void *ptr1, *ptr2, *ptr3; int ans; x0 = 0; y0 = 0; x2 = PCB->MaxWidth; y2 = PCB->MaxHeight; Crosshair.X = MIN (Crosshair.MaxX, MAX (Crosshair.MinX, X)); Crosshair.Y = MIN (Crosshair.MaxY, MAX (Crosshair.MinY, Y)); if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB)) { ans = SearchScreen (Crosshair.X, Crosshair.Y, PAD_TYPE | PIN_TYPE, &ptr1, &ptr2, &ptr3); if (ans == NO_TYPE && !PCB->RatDraw) ans = SearchScreen (Crosshair.X, Crosshair.Y, VIA_TYPE | LINEPOINT_TYPE, &ptr1, &ptr2, &ptr3); if (ans == NO_TYPE && !PCB->RatDraw) ans = SearchScreen (Crosshair.X, Crosshair.Y, ELEMENT_TYPE, &ptr1, &ptr2, &ptr3); } else ans = NO_TYPE; /* avoid self-snapping */ if (Settings.Mode == MOVE_MODE) { switch (Crosshair.AttachedObject.Type) { case ELEMENT_TYPE: if ((ans & (PAD_TYPE | PIN_TYPE)) && ptr1 == Crosshair.AttachedObject.Ptr1) ans = NO_TYPE; break; case VIA_TYPE: /* just avoid snapping to any other vias */ if (ans & PIN_TYPES) ans = NO_TYPE; break; } } if (PCB->RatDraw) { x0 = -600; y0 = -600; } else { /* check if new position is inside the output window * This might not be true after the window has been resized. * In this case we just set it to the center of the window or * with respect to the grid (if possible) */ if (Crosshair.X < x0 || Crosshair.X > x2) { if (x2 + 1 >= PCB->Grid) /* there must be a point that matches the grid * so we just have to look for it with some integer * calculations */ x0 = GRIDFIT_X (PCB->Grid, PCB->Grid); else x0 = (x2) / 2; } else /* check if the new position matches the grid */ x0 = GRIDFIT_X (Crosshair.X, PCB->Grid); /* do the same for the second coordinate */ if (Crosshair.Y < y0 || Crosshair.Y > y2) { if (y2 + 1 >= PCB->Grid) y0 = GRIDFIT_Y (PCB->Grid, PCB->Grid); else y0 = (y2) / 2; } else y0 = GRIDFIT_Y (Crosshair.Y, PCB->Grid); if (Marked.status && TEST_FLAG (ORTHOMOVEFLAG, PCB)) { int dx = Crosshair.X - Marked.X; int dy = Crosshair.Y - Marked.Y; if (ABS (dx) > ABS (dy)) y0 = Marked.Y; else x0 = Marked.X; } } if (ans & PAD_TYPE) { PadTypePtr pad = (PadTypePtr) ptr2; LocationType px, py; px = (pad->Point1.X + pad->Point2.X) / 2; py = (pad->Point1.Y + pad->Point2.Y) / 2; if (!gui->shift_is_pressed() || (SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > SQUARE (px - Crosshair.X) + SQUARE (py - Crosshair.Y))) { x0 = px; y0 = py; } } else if (ans & (PIN_TYPE | VIA_TYPE)) { PinTypePtr pin = (PinTypePtr) ptr2; if (!gui->shift_is_pressed() || (SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > SQUARE (pin->X - Crosshair.X) + SQUARE (pin->Y - Crosshair.Y))) { x0 = pin->X; y0 = pin->Y; } } else if (ans & LINEPOINT_TYPE) { PointTypePtr pnt = (PointTypePtr) ptr3; if (((x0 - Crosshair.X) * (x0 - Crosshair.X) + (y0 - Crosshair.Y) * (y0 - Crosshair.Y)) > ((pnt->X - Crosshair.X) * (pnt->X - Crosshair.X) + (pnt->Y - Crosshair.Y) * (pnt->Y - Crosshair.Y))) { x0 = pnt->X; y0 = pnt->Y; } } else if (ans & ELEMENT_TYPE) { ElementTypePtr el = (ElementTypePtr) ptr1; if (SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > SQUARE (el->MarkX - Crosshair.X) + SQUARE (el->MarkY - Crosshair.Y)) { x0 = el->MarkX; y0 = el->MarkY; } } if (x0 >= 0 && y0 >= 0) { Crosshair.X = x0; Crosshair.Y = y0; } if (Settings.Mode == ARROW_MODE) { ans = SearchScreen (Crosshair.X, Crosshair.Y, LINEPOINT_TYPE, &ptr1, &ptr2, &ptr3); if (ans == NO_TYPE) hid_action("PointCursor"); else if (!TEST_FLAG(SELECTEDFLAG, (LineType *)ptr2)) hid_actionl("PointCursor","True", NULL); } if (Settings.Mode == LINE_MODE && Crosshair.AttachedLine.State != STATE_FIRST && TEST_FLAG (AUTODRCFLAG, PCB)) EnforceLineDRC (); gui->set_crosshair (Crosshair.X, Crosshair.Y, HID_SC_DO_NOTHING); }
static void drc_refresh_cb (gpointer data) { hid_actionl ("DRC", NULL); }
/* --------------------------------------------------------------------------- * recalculates the passed coordinates to fit the current grid setting */ void FitCrosshairIntoGrid (Coord X, Coord Y) { Coord nearest_grid_x, nearest_grid_y; void *ptr1, *ptr2, *ptr3; struct snap_data snap_data; int ans; Crosshair.X = CLAMP (X, Crosshair.MinX, Crosshair.MaxX); Crosshair.Y = CLAMP (Y, Crosshair.MinY, Crosshair.MaxY); if (PCB->RatDraw) { nearest_grid_x = -MIL_TO_COORD (6); nearest_grid_y = -MIL_TO_COORD (6); } else { nearest_grid_x = GridFit (Crosshair.X, PCB->Grid, PCB->GridOffsetX); nearest_grid_y = GridFit (Crosshair.Y, PCB->Grid, PCB->GridOffsetY); if (Marked.status && TEST_FLAG (ORTHOMOVEFLAG, PCB)) { Coord dx = Crosshair.X - Marked.X; Coord dy = Crosshair.Y - Marked.Y; if (ABS (dx) > ABS (dy)) nearest_grid_y = Marked.Y; else nearest_grid_x = Marked.X; } } snap_data.crosshair = &Crosshair; snap_data.nearest_sq_dist = crosshair_sq_dist (&Crosshair, nearest_grid_x, nearest_grid_y); snap_data.nearest_is_grid = true; snap_data.x = nearest_grid_x; snap_data.y = nearest_grid_y; ans = NO_TYPE; if (!PCB->RatDraw) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, ELEMENT_TYPE, &ptr1, &ptr2, &ptr3); if (ans & ELEMENT_TYPE) { ElementType *el = (ElementType *) ptr1; check_snap_object (&snap_data, el->MarkX, el->MarkY, false); } ans = NO_TYPE; if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, PAD_TYPE, &ptr1, &ptr2, &ptr3); /* Avoid self-snapping when moving */ if (ans != NO_TYPE && Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == ELEMENT_TYPE && ptr1 == Crosshair.AttachedObject.Ptr1) ans = NO_TYPE; if (ans != NO_TYPE && ( Settings.Mode == LINE_MODE || (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == LINEPOINT_TYPE))) { PadTypePtr pad = (PadTypePtr) ptr2; LayerType *desired_layer; Cardinal desired_group; Cardinal SLayer, CLayer; int found_our_layer = false; desired_layer = CURRENT; if (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == LINEPOINT_TYPE) { desired_layer = (LayerType *)Crosshair.AttachedObject.Ptr1; } /* find layer groups of the component side and solder side */ SLayer = GetLayerGroupNumberByNumber (solder_silk_layer); CLayer = GetLayerGroupNumberByNumber (component_silk_layer); desired_group = TEST_FLAG (ONSOLDERFLAG, pad) ? SLayer : CLayer; GROUP_LOOP (PCB->Data, desired_group); { if (layer == desired_layer) { found_our_layer = true; break; } } END_LOOP; if (found_our_layer == false) ans = NO_TYPE; } if (ans != NO_TYPE) { PadType *pad = (PadType *)ptr2; check_snap_object (&snap_data, (pad->Point1.X + pad->Point2.X) / 2, (pad->Point1.Y + pad->Point2.Y) / 2, true); } ans = NO_TYPE; if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, PIN_TYPE, &ptr1, &ptr2, &ptr3); /* Avoid self-snapping when moving */ if (ans != NO_TYPE && Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == ELEMENT_TYPE && ptr1 == Crosshair.AttachedObject.Ptr1) ans = NO_TYPE; if (ans != NO_TYPE) { PinType *pin = (PinType *)ptr2; check_snap_object (&snap_data, pin->X, pin->Y, true); } ans = NO_TYPE; if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, VIA_TYPE, &ptr1, &ptr2, &ptr3); /* Avoid snapping vias to any other vias */ if (Settings.Mode == MOVE_MODE && Crosshair.AttachedObject.Type == VIA_TYPE && (ans & PIN_TYPES)) ans = NO_TYPE; if (ans != NO_TYPE) { PinType *pin = (PinType *)ptr2; check_snap_object (&snap_data, pin->X, pin->Y, true); } ans = NO_TYPE; if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, LINEPOINT_TYPE, &ptr1, &ptr2, &ptr3); if (ans != NO_TYPE) { PointType *pnt = (PointType *)ptr3; check_snap_object (&snap_data, pnt->X, pnt->Y, true); } check_snap_offgrid_line (&snap_data, nearest_grid_x, nearest_grid_y); ans = NO_TYPE; if (TEST_FLAG (SNAPPINFLAG, PCB)) ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, POLYGONPOINT_TYPE, &ptr1, &ptr2, &ptr3); if (ans != NO_TYPE) { PointType *pnt = (PointType *)ptr3; check_snap_object (&snap_data, pnt->X, pnt->Y, true); } if (snap_data.x >= 0 && snap_data.y >= 0) { Crosshair.X = snap_data.x; Crosshair.Y = snap_data.y; } if (Settings.Mode == ARROW_MODE) { ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y, LINEPOINT_TYPE, &ptr1, &ptr2, &ptr3); if (ans == NO_TYPE) hid_action("PointCursor"); else if (!TEST_FLAG(SELECTEDFLAG, (LineType *)ptr2)) hid_actionl("PointCursor","True", NULL); } if (Settings.Mode == LINE_MODE && Crosshair.AttachedLine.State != STATE_FIRST && TEST_FLAG (AUTODRCFLAG, PCB)) EnforceLineDRC (); gui->set_crosshair (Crosshair.X, Crosshair.Y, HID_SC_DO_NOTHING); }
static int FontEdit (int argc, char **argv, Coord Ux, Coord Uy) { FontType *font; SymbolType *symbol; LayerType *lfont, *lorig, *lwidth, *lgrid; int s, l; if (hid_actionl ("New", "Font", 0)) { return 1; } Settings.grid_unit = get_unit_struct("mil"); Settings.Bloat = PCB->Bloat = 1; Settings.Shrink = PCB->Shrink = 1; Settings.minWid = PCB->minWid = 1; Settings.minSlk = PCB->minSlk = 1; MoveLayerToGroup (max_copper_layer + TOP_SILK_LAYER, 0); MoveLayerToGroup (max_copper_layer + BOTTOM_SILK_LAYER, 1); while (PCB->Data->LayerN > 4) { MoveLayer (4, -1); } for (l = 0; l < 4; l++) { MoveLayerToGroup (l, l); } PCB->MaxWidth = CELL_SIZE * 18; PCB->MaxHeight = CELL_SIZE * ((MAX_FONTPOSITION + 15) / 16 + 2); PCB->Grid = MIL_TO_COORD (5); PCB->Data->Layer[0].Name = strdup ("Font"); PCB->Data->Layer[1].Name = strdup ("OrigFont"); PCB->Data->Layer[2].Name = strdup ("Width"); PCB->Data->Layer[3].Name = strdup ("Grid"); hid_action ("PCBChanged"); hid_action ("LayersChanged"); lfont = PCB->Data->Layer + 0; lorig = PCB->Data->Layer + 1; lwidth = PCB->Data->Layer + 2; lgrid = PCB->Data->Layer + 3; font = &PCB->Font; for (s = 0; s <= MAX_FONTPOSITION; s++) { Coord ox = (s % 16 + 1) * CELL_SIZE; Coord oy = (s / 16 + 1) * CELL_SIZE; Coord w, miny, maxy, maxx = 0; symbol = &font->Symbol[s]; miny = MIL_TO_COORD (5); maxy = font->MaxHeight; for (l = 0; l < symbol->LineN; l++) { CreateDrawnLineOnLayer (lfont, symbol->Line[l].Point1.X + ox, symbol->Line[l].Point1.Y + oy, symbol->Line[l].Point2.X + ox, symbol->Line[l].Point2.Y + oy, symbol->Line[l].Thickness, symbol->Line[l].Thickness, NoFlags ()); CreateDrawnLineOnLayer (lorig, symbol->Line[l].Point1.X + ox, symbol->Line[l].Point1.Y + oy, symbol->Line[l].Point2.X + ox, symbol->Line[l].Point2.Y + oy, symbol->Line[l].Thickness, symbol->Line[l].Thickness, NoFlags ()); if (maxx < symbol->Line[l].Point1.X) { maxx = symbol->Line[l].Point1.X; } if (maxx < symbol->Line[l].Point2.X) { maxx = symbol->Line[l].Point2.X; } } w = maxx + symbol->Delta + ox; CreateDrawnLineOnLayer (lwidth, w, miny + oy, w, maxy + oy, MIL_TO_COORD (1), MIL_TO_COORD (1), NoFlags ()); } for (l = 0; l < 16; l++) { int x = (l + 1) * CELL_SIZE; CreateDrawnLineOnLayer (lgrid, x, 0, x, PCB->MaxHeight, MIL_TO_COORD (1), MIL_TO_COORD (1), NoFlags ()); } for (l = 0; l <= MAX_FONTPOSITION / 16 + 1; l++) { int y = (l + 1) * CELL_SIZE; CreateDrawnLineOnLayer (lgrid, 0, y, PCB->MaxWidth, y, MIL_TO_COORD (1), MIL_TO_COORD (1), NoFlags ()); } return 0; }
static int FontEdit (int argc, char **argv, int Ux, int Uy) { FontType *font; SymbolType *symbol; LayerTypePtr lfont, lorig, lwidth, lgrid; int s, l; if (hid_actionl ("New", "Font", 0)) return 1; while (PCB->Data->LayerN > 4) MoveLayer (4, -1); for (l = 0; l < 4; l++) { MoveLayerToGroup (l, l); } PCB->MaxWidth = CELL_SIZE * 18; PCB->MaxHeight = CELL_SIZE * ((MAX_FONTPOSITION + 15) / 16 + 2); PCB->Grid = 500.0; PCB->Data->Layer[0].Name = MyStrdup ("Font", "FontEdit"); PCB->Data->Layer[1].Name = MyStrdup ("OrigFont", "FontEdit"); PCB->Data->Layer[2].Name = MyStrdup ("Width", "FontEdit"); PCB->Data->Layer[3].Name = MyStrdup ("Grid", "FontEdit"); hid_action ("PCBChanged"); hid_action ("LayersChanged"); lfont = PCB->Data->Layer + 0; lorig = PCB->Data->Layer + 1; lwidth = PCB->Data->Layer + 2; lgrid = PCB->Data->Layer + 3; font = &PCB->Font; for (s = 0; s <= MAX_FONTPOSITION; s++) { int ox = (s % 16 + 1) * CELL_SIZE; int oy = (s / 16 + 1) * CELL_SIZE; int w, miny, maxy, maxx = 0; symbol = &font->Symbol[s]; miny = 500; maxy = font->MaxHeight; for (l = 0; l < symbol->LineN; l++) { CreateDrawnLineOnLayer (lfont, symbol->Line[l].Point1.X + ox, symbol->Line[l].Point1.Y + oy, symbol->Line[l].Point2.X + ox, symbol->Line[l].Point2.Y + oy, symbol->Line[l].Thickness, symbol->Line[l].Thickness, NoFlags ()); CreateDrawnLineOnLayer (lorig, symbol->Line[l].Point1.X + ox, symbol->Line[l].Point1.Y + oy, symbol->Line[l].Point2.X + ox, symbol->Line[l].Point2.Y + oy, symbol->Line[l].Thickness, symbol->Line[l].Thickness, NoFlags ()); if (maxx < symbol->Line[l].Point1.X) maxx = symbol->Line[l].Point1.X; if (maxx < symbol->Line[l].Point2.X) maxx = symbol->Line[l].Point2.X; } w = maxx + symbol->Delta + ox; CreateDrawnLineOnLayer (lwidth, w, miny + oy, w, maxy + oy, 100, 100, NoFlags ()); } for (l = 0; l < 16; l++) { int x = (l + 1) * CELL_SIZE; CreateDrawnLineOnLayer (lgrid, x, 0, x, PCB->MaxHeight, 100, 100, NoFlags ()); } for (l = 0; l <= MAX_FONTPOSITION / 16 + 1; l++) { int y = (l + 1) * CELL_SIZE; CreateDrawnLineOnLayer (lgrid, 0, y, PCB->MaxWidth, y, 100, 100, NoFlags ()); } return 0; }
/* If user hits a key instead of the mouse button, we'll abort unless | it's one of the cursor keys. Move the layout if a cursor key. */ static gboolean loop_key_press_cb (GtkWidget * drawing_area, GdkEventKey * kev, GMainLoop ** loop) { ModifierKeysState mk; GdkModifierType state; gint ksym = kev->keyval; if (ghid_is_modifier_key_sym (ksym)) return TRUE; state = (GdkModifierType) (kev->state); mk = ghid_modifier_keys_state (&state); /* Duplicate the cursor key actions in gui-output-events.c */ switch (ksym) { case GDK_Up: if (mk == CONTROL_PRESSED) { hid_actionl ("Display", "Scroll", "8", NULL); hid_actionl ("Display", "Scroll", "0", NULL); } else if (mk == SHIFT_PRESSED) hid_actionl ("MovePointer", "0", "-10", NULL); else if (mk == NONE_PRESSED) hid_actionl ("MovePointer", "0", "-1", NULL); break; case GDK_Down: if (mk == CONTROL_PRESSED) { hid_actionl ("Display", "Scroll", "2", NULL); hid_actionl ("Display", "Scroll", "0", NULL); } else if (mk == SHIFT_PRESSED) hid_actionl ("MovePointer", "0", "10", NULL); else if (mk == NONE_PRESSED) hid_actionl ("MovePointer", "0", "1", NULL); break; case GDK_Left: if (mk == CONTROL_PRESSED) { hid_actionl ("Display", "Scroll", "4", NULL); hid_actionl ("Display", "Scroll", "0", NULL); } else if (mk == SHIFT_PRESSED) hid_actionl ("MovePointer", "-10", "0", NULL); else if (mk == NONE_PRESSED) hid_actionl ("MovePointer", "-1", "0", NULL); break; case GDK_Right: if (mk == CONTROL_PRESSED) { hid_actionl ("Display", "Scroll", "6", NULL); hid_actionl ("Display", "Scroll", "0", NULL); } else if (mk == SHIFT_PRESSED) hid_actionl ("MovePointer", "10", "0", NULL); else if (mk == NONE_PRESSED) hid_actionl ("MovePointer", "1", "0", NULL); break; case GDK_Return: /* Accept cursor location */ if (g_main_loop_is_running (*loop)) g_main_loop_quit (*loop); break; default: /* Abort */ got_location = FALSE; if (g_main_loop_is_running (*loop)) g_main_loop_quit (*loop); break; } return TRUE; }