Index: trunk/src/layer.c =================================================================== --- trunk/src/layer.c (revision 4913) +++ trunk/src/layer.c (revision 4914) @@ -32,6 +32,7 @@ #include "layer.h" #include "hid_actions.h" #include "compat_misc.h" +#include "undo.h" /* * Used by SaveStackAndVisibility() and @@ -846,6 +847,72 @@ #undef APPEND +/* --------------------------------------------------------------------------- + * move layer + * moves the selected layers to a new index in the layer list. + */ + +static void move_one_thermal(int old_index, int new_index, pcb_pin_t * pin) +{ + int t1 = 0, i; + int oi = old_index, ni = new_index; + + if (old_index != -1) + t1 = PCB_FLAG_THERM_GET(old_index, pin); + + if (oi == -1) + oi = MAX_LAYER - 1; /* inserting a layer */ + if (ni == -1) + ni = MAX_LAYER - 1; /* deleting a layer */ + + if (oi < ni) { + for (i = oi; i < ni; i++) + PCB_FLAG_THERM_ASSIGN(i, PCB_FLAG_THERM_GET(i + 1, pin), pin); + } + else { + for (i = oi; i > ni; i--) + PCB_FLAG_THERM_ASSIGN(i, PCB_FLAG_THERM_GET(i - 1, pin), pin); + } + + if (new_index != -1) + PCB_FLAG_THERM_ASSIGN(new_index, t1, pin); + else + PCB_FLAG_THERM_ASSIGN(ni, 0, pin); +} + +static void move_all_thermals(int old_index, int new_index) +{ + VIA_LOOP(PCB->Data); + { + move_one_thermal(old_index, new_index, via); + } + END_LOOP; + + ALLPIN_LOOP(PCB->Data); + { + move_one_thermal(old_index, new_index, pin); + } + ENDALL_LOOP; +} + +static int LastLayerInComponentGroup(int layer) +{ + int cgroup = GetLayerGroupNumberByNumber(max_group + COMPONENT_LAYER); + int lgroup = GetLayerGroupNumberByNumber(layer); + if (cgroup == lgroup && PCB->LayerGroups.Number[lgroup] == 2) + return 1; + return 0; +} + +static int LastLayerInSolderGroup(int layer) +{ + int sgroup = GetLayerGroupNumberByNumber(max_group + SOLDER_LAYER); + int lgroup = GetLayerGroupNumberByNumber(layer); + if (sgroup == lgroup && PCB->LayerGroups.Number[lgroup] == 2) + return 1; + return 0; +} + /* changes the name of a layer; memory has to be already allocated */ pcb_bool pcb_layer_change_name(pcb_layer_t *Layer, char *Name) { @@ -854,3 +921,118 @@ pcb_hid_action("LayersChanged"); return (pcb_true); } + +int MoveLayer(int old_index, int new_index) +{ + int groups[MAX_LAYER + 2], l, g; + pcb_layer_t saved_layer; + int saved_group; + + AddLayerChangeToUndoList(old_index, new_index); + IncrementUndoSerialNumber(); + + if (old_index < -1 || old_index >= max_copper_layer) { + pcb_message(PCB_MSG_DEFAULT, "Invalid old layer %d for move: must be -1..%d\n", old_index, max_copper_layer - 1); + return 1; + } + if (new_index < -1 || new_index > max_copper_layer || new_index >= MAX_LAYER) { + pcb_message(PCB_MSG_DEFAULT, "Invalid new layer %d for move: must be -1..%d\n", new_index, max_copper_layer); + return 1; + } + if (old_index == new_index) + return 0; + + if (new_index == -1 && LastLayerInComponentGroup(old_index)) { + gui->confirm_dialog("You can't delete the last top-side layer\n", "Ok", NULL); + return 1; + } + + if (new_index == -1 && LastLayerInSolderGroup(old_index)) { + gui->confirm_dialog("You can't delete the last bottom-side layer\n", "Ok", NULL); + return 1; + } + + for (g = 0; g < MAX_LAYER + 2; g++) + groups[g] = -1; + + for (g = 0; g < MAX_LAYER; g++) + for (l = 0; l < PCB->LayerGroups.Number[g]; l++) + groups[PCB->LayerGroups.Entries[g][l]] = g; + + if (old_index == -1) { + pcb_layer_t *lp; + if (max_copper_layer == MAX_LAYER) { + pcb_message(PCB_MSG_DEFAULT, "No room for new layers\n"); + return 1; + } + /* Create a new layer at new_index. */ + lp = &PCB->Data->Layer[new_index]; + memmove(&PCB->Data->Layer[new_index + 1], + &PCB->Data->Layer[new_index], (max_copper_layer - new_index + 2) * sizeof(pcb_layer_t)); + memmove(&groups[new_index + 1], &groups[new_index], (max_copper_layer - new_index + 2) * sizeof(int)); + max_copper_layer++; + memset(lp, 0, sizeof(pcb_layer_t)); + lp->On = 1; + lp->Name = pcb_strdup("New Layer"); + lp->Color = conf_core.appearance.color.layer[new_index]; + lp->SelectedColor = conf_core.appearance.color.layer_selected[new_index]; + for (l = 0; l < max_copper_layer; l++) + if (LayerStack[l] >= new_index) + LayerStack[l]++; + LayerStack[max_copper_layer - 1] = new_index; + } + else if (new_index == -1) { + /* Delete the layer at old_index */ + memmove(&PCB->Data->Layer[old_index], + &PCB->Data->Layer[old_index + 1], (max_copper_layer - old_index + 2 - 1) * sizeof(pcb_layer_t)); + memset(&PCB->Data->Layer[max_copper_layer + 1], 0, sizeof(pcb_layer_t)); + memmove(&groups[old_index], &groups[old_index + 1], (max_copper_layer - old_index + 2 - 1) * sizeof(int)); + for (l = 0; l < max_copper_layer; l++) + if (LayerStack[l] == old_index) + memmove(LayerStack + l, LayerStack + l + 1, (max_copper_layer - l - 1) * sizeof(LayerStack[0])); + max_copper_layer--; + for (l = 0; l < max_copper_layer; l++) + if (LayerStack[l] > old_index) + LayerStack[l]--; + } + else { + /* Move an existing layer */ + memcpy(&saved_layer, &PCB->Data->Layer[old_index], sizeof(pcb_layer_t)); + saved_group = groups[old_index]; + if (old_index < new_index) { + memmove(&PCB->Data->Layer[old_index], &PCB->Data->Layer[old_index + 1], (new_index - old_index) * sizeof(pcb_layer_t)); + memmove(&groups[old_index], &groups[old_index + 1], (new_index - old_index) * sizeof(int)); + } + else { + memmove(&PCB->Data->Layer[new_index + 1], &PCB->Data->Layer[new_index], (old_index - new_index) * sizeof(pcb_layer_t)); + memmove(&groups[new_index + 1], &groups[new_index], (old_index - new_index) * sizeof(int)); + } + memcpy(&PCB->Data->Layer[new_index], &saved_layer, sizeof(pcb_layer_t)); + groups[new_index] = saved_group; + } + + move_all_thermals(old_index, new_index); + + for (g = 0; g < MAX_LAYER; g++) + PCB->LayerGroups.Number[g] = 0; + for (l = 0; l < max_copper_layer + 2; l++) { + int i; + g = groups[l]; + if (g >= 0) { + i = PCB->LayerGroups.Number[g]++; + PCB->LayerGroups.Entries[g][i] = l; + } + } + + for (g = 0; g < MAX_LAYER; g++) + if (PCB->LayerGroups.Number[g] == 0) { + memmove(&PCB->LayerGroups.Number[g], + &PCB->LayerGroups.Number[g + 1], (MAX_LAYER - g - 1) * sizeof(PCB->LayerGroups.Number[g])); + memmove(&PCB->LayerGroups.Entries[g], + &PCB->LayerGroups.Entries[g + 1], (MAX_LAYER - g - 1) * sizeof(PCB->LayerGroups.Entries[g])); + } + + pcb_hid_action("LayersChanged"); + gui->invalidate_all(); + return 0; +} Index: trunk/src/layer.h =================================================================== --- trunk/src/layer.h (revision 4913) +++ trunk/src/layer.h (revision 4914) @@ -225,4 +225,9 @@ /* changes the name of a layer; memory has to be already allocated */ pcb_bool pcb_layer_change_name(pcb_layer_t *Layer, char *Name); +/* index is 0..MAX_LAYER-1. If old_index is -1, a new layer is + inserted at that index. If new_index is -1, the specified layer is + deleted. Returns non-zero on error, zero if OK. */ +int MoveLayer(int old_index, int new_index); + #endif Index: trunk/src/move.c =================================================================== --- trunk/src/move.c (revision 4913) +++ trunk/src/move.c (revision 4914) @@ -163,186 +163,6 @@ return (changed); } -/* --------------------------------------------------------------------------- - * moves the selected layers to a new index in the layer list. - */ - -static void move_one_thermal(int old_index, int new_index, pcb_pin_t * pin) -{ - int t1 = 0, i; - int oi = old_index, ni = new_index; - - if (old_index != -1) - t1 = PCB_FLAG_THERM_GET(old_index, pin); - - if (oi == -1) - oi = MAX_LAYER - 1; /* inserting a layer */ - if (ni == -1) - ni = MAX_LAYER - 1; /* deleting a layer */ - - if (oi < ni) { - for (i = oi; i < ni; i++) - PCB_FLAG_THERM_ASSIGN(i, PCB_FLAG_THERM_GET(i + 1, pin), pin); - } - else { - for (i = oi; i > ni; i--) - PCB_FLAG_THERM_ASSIGN(i, PCB_FLAG_THERM_GET(i - 1, pin), pin); - } - - if (new_index != -1) - PCB_FLAG_THERM_ASSIGN(new_index, t1, pin); - else - PCB_FLAG_THERM_ASSIGN(ni, 0, pin); -} - -static void move_all_thermals(int old_index, int new_index) -{ - VIA_LOOP(PCB->Data); - { - move_one_thermal(old_index, new_index, via); - } - END_LOOP; - - ALLPIN_LOOP(PCB->Data); - { - move_one_thermal(old_index, new_index, pin); - } - ENDALL_LOOP; -} - -static int LastLayerInComponentGroup(int layer) -{ - int cgroup = GetLayerGroupNumberByNumber(max_group + COMPONENT_LAYER); - int lgroup = GetLayerGroupNumberByNumber(layer); - if (cgroup == lgroup && PCB->LayerGroups.Number[lgroup] == 2) - return 1; - return 0; -} - -static int LastLayerInSolderGroup(int layer) -{ - int sgroup = GetLayerGroupNumberByNumber(max_group + SOLDER_LAYER); - int lgroup = GetLayerGroupNumberByNumber(layer); - if (sgroup == lgroup && PCB->LayerGroups.Number[lgroup] == 2) - return 1; - return 0; -} - -int MoveLayer(int old_index, int new_index) -{ - int groups[MAX_LAYER + 2], l, g; - pcb_layer_t saved_layer; - int saved_group; - - AddLayerChangeToUndoList(old_index, new_index); - IncrementUndoSerialNumber(); - - if (old_index < -1 || old_index >= max_copper_layer) { - pcb_message(PCB_MSG_DEFAULT, "Invalid old layer %d for move: must be -1..%d\n", old_index, max_copper_layer - 1); - return 1; - } - if (new_index < -1 || new_index > max_copper_layer || new_index >= MAX_LAYER) { - pcb_message(PCB_MSG_DEFAULT, "Invalid new layer %d for move: must be -1..%d\n", new_index, max_copper_layer); - return 1; - } - if (old_index == new_index) - return 0; - - if (new_index == -1 && LastLayerInComponentGroup(old_index)) { - gui->confirm_dialog("You can't delete the last top-side layer\n", "Ok", NULL); - return 1; - } - - if (new_index == -1 && LastLayerInSolderGroup(old_index)) { - gui->confirm_dialog("You can't delete the last bottom-side layer\n", "Ok", NULL); - return 1; - } - - for (g = 0; g < MAX_LAYER + 2; g++) - groups[g] = -1; - - for (g = 0; g < MAX_LAYER; g++) - for (l = 0; l < PCB->LayerGroups.Number[g]; l++) - groups[PCB->LayerGroups.Entries[g][l]] = g; - - if (old_index == -1) { - pcb_layer_t *lp; - if (max_copper_layer == MAX_LAYER) { - pcb_message(PCB_MSG_DEFAULT, "No room for new layers\n"); - return 1; - } - /* Create a new layer at new_index. */ - lp = &PCB->Data->Layer[new_index]; - memmove(&PCB->Data->Layer[new_index + 1], - &PCB->Data->Layer[new_index], (max_copper_layer - new_index + 2) * sizeof(pcb_layer_t)); - memmove(&groups[new_index + 1], &groups[new_index], (max_copper_layer - new_index + 2) * sizeof(int)); - max_copper_layer++; - memset(lp, 0, sizeof(pcb_layer_t)); - lp->On = 1; - lp->Name = pcb_strdup("New Layer"); - lp->Color = conf_core.appearance.color.layer[new_index]; - lp->SelectedColor = conf_core.appearance.color.layer_selected[new_index]; - for (l = 0; l < max_copper_layer; l++) - if (LayerStack[l] >= new_index) - LayerStack[l]++; - LayerStack[max_copper_layer - 1] = new_index; - } - else if (new_index == -1) { - /* Delete the layer at old_index */ - memmove(&PCB->Data->Layer[old_index], - &PCB->Data->Layer[old_index + 1], (max_copper_layer - old_index + 2 - 1) * sizeof(pcb_layer_t)); - memset(&PCB->Data->Layer[max_copper_layer + 1], 0, sizeof(pcb_layer_t)); - memmove(&groups[old_index], &groups[old_index + 1], (max_copper_layer - old_index + 2 - 1) * sizeof(int)); - for (l = 0; l < max_copper_layer; l++) - if (LayerStack[l] == old_index) - memmove(LayerStack + l, LayerStack + l + 1, (max_copper_layer - l - 1) * sizeof(LayerStack[0])); - max_copper_layer--; - for (l = 0; l < max_copper_layer; l++) - if (LayerStack[l] > old_index) - LayerStack[l]--; - } - else { - /* Move an existing layer */ - memcpy(&saved_layer, &PCB->Data->Layer[old_index], sizeof(pcb_layer_t)); - saved_group = groups[old_index]; - if (old_index < new_index) { - memmove(&PCB->Data->Layer[old_index], &PCB->Data->Layer[old_index + 1], (new_index - old_index) * sizeof(pcb_layer_t)); - memmove(&groups[old_index], &groups[old_index + 1], (new_index - old_index) * sizeof(int)); - } - else { - memmove(&PCB->Data->Layer[new_index + 1], &PCB->Data->Layer[new_index], (old_index - new_index) * sizeof(pcb_layer_t)); - memmove(&groups[new_index + 1], &groups[new_index], (old_index - new_index) * sizeof(int)); - } - memcpy(&PCB->Data->Layer[new_index], &saved_layer, sizeof(pcb_layer_t)); - groups[new_index] = saved_group; - } - - move_all_thermals(old_index, new_index); - - for (g = 0; g < MAX_LAYER; g++) - PCB->LayerGroups.Number[g] = 0; - for (l = 0; l < max_copper_layer + 2; l++) { - int i; - g = groups[l]; - if (g >= 0) { - i = PCB->LayerGroups.Number[g]++; - PCB->LayerGroups.Entries[g][i] = l; - } - } - - for (g = 0; g < MAX_LAYER; g++) - if (PCB->LayerGroups.Number[g] == 0) { - memmove(&PCB->LayerGroups.Number[g], - &PCB->LayerGroups.Number[g + 1], (MAX_LAYER - g - 1) * sizeof(PCB->LayerGroups.Number[g])); - memmove(&PCB->LayerGroups.Entries[g], - &PCB->LayerGroups.Entries[g + 1], (MAX_LAYER - g - 1) * sizeof(PCB->LayerGroups.Entries[g])); - } - - pcb_hid_action("LayersChanged"); - gui->invalidate_all(); - return 0; -} - /* --------------------------------------------------------------------------- */ static const char movelayer_syntax[] = "MoveLayer(old,new)"; Index: trunk/src/move.h =================================================================== --- trunk/src/move.h (revision 4913) +++ trunk/src/move.h (revision 4914) @@ -55,9 +55,4 @@ void *MoveObjectAndRubberband(int, void *, void *, void *, pcb_coord_t, pcb_coord_t); pcb_bool MoveSelectedObjectsToLayer(pcb_layer_t *); -/* index is 0..MAX_LAYER-1. If old_index is -1, a new layer is - inserted at that index. If new_index is -1, the specified layer is - deleted. Returns non-zero on error, zero if OK. */ -int MoveLayer(int old_index, int new_index); - #endif