Commit 178f48bd authored by Ivica Bukvic's avatar Ivica Bukvic
Browse files

added ability to readjust locations when using operations that fundamentally...

added ability to readjust locations when using operations that fundamentally alter glists. Added dirty flag to store operations. Disabled debugging output.
parent 4c740057
......@@ -61,6 +61,8 @@ extern void canvas_setbounds(t_canvas *x, int x1, int y1, int x2, int y2);
int canvas_apply_restore_original_position(t_canvas *x, int orig_pos);
extern void canvas_draw_gop_resize_hooks(t_canvas *x);
static void canvas_font(t_canvas *x, t_floatarg font, t_floatarg oldfont, t_floatarg resize, t_floatarg preview);
// for updating preset_node locations in case of operations that alter glist object locations (tofront/back, cut, delete, undo/redo cut/delete)
extern void glob_preset_node_list_check_loc_and_update(void);
struct _outlet
{
......@@ -800,6 +802,8 @@ void canvas_undo_cut(t_canvas *x, void *z, int action)
}
}
canvas_redraw(x);
glob_preset_node_list_check_loc_and_update();
}
}
}
......@@ -815,6 +819,7 @@ void canvas_undo_cut(t_canvas *x, void *z, int action)
for (i = 0; i < buf->n_obj; i++)
glist_select(x, glist_nth(x, buf->p_a[i]));
canvas_doclear(x);
glob_preset_node_list_check_loc_and_update();
}
else if (mode == UCUT_TEXT)
{
......@@ -1282,6 +1287,8 @@ void canvas_undo_arrange(t_canvas *x, void *z, int action)
// and finally redraw canvas
canvas_redraw(x);
glob_preset_node_list_check_loc_and_update();
}
}
else if (action == UNDO_REDO) {
......@@ -2294,6 +2301,7 @@ static void canvas_doarrange(t_canvas *x, t_float which, t_gobj *oldy, t_gobj *o
canvas_redraw(x);
}
canvas_dirty(x, 1);
glob_preset_node_list_check_loc_and_update();
}
/* called from the gui when a popup menu comes back with "properties,"
......@@ -3501,6 +3509,7 @@ void canvas_key(t_canvas *x, t_symbol *s, int ac, t_atom *av)
// canvas_undo_set_cut(x, UCUT_CLEAR), "clear");
canvas_undo_add(x, 3, "clear", canvas_undo_set_cut(x, UCUT_CLEAR));
canvas_doclear(x);
glob_preset_node_list_check_loc_and_update();
}
}
/* check for arrow keys */
......@@ -4232,6 +4241,7 @@ static void canvas_cut(t_canvas *x)
canvas_undo_add(x, 3, "cut", canvas_undo_set_cut(x, UCUT_CUT));
canvas_copy(x);
canvas_doclear(x);
glob_preset_node_list_check_loc_and_update();
paste_xyoffset = 0;
sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
}
......
......@@ -10,11 +10,11 @@
#include "x_preset.h"
#include "s_stuff.h"
#define DEBUG(x)
//#define PH_DEBUG
//TODO: changes in order happen when cutting, undo cut, undo paste,
// delete, undo delete, to front, and to back
// this should trigger cascading check for all preset_nodes
// changes in order happen when doing one of the following: cut,
// undo cut, delete, undo delete, to front, and to back.
// this will trigger cascading check for all preset_nodes
// is there a way to limit it to ones that are affected?
// potentially... by taking all the ordinal values above the one moved
// e.g. if object 1,5 was moved, everything above it
......@@ -22,6 +22,10 @@
// reevaluating moved object (if applicable)
// this does not affect objects like 2 or 2,7
// since it is a different branch altogether
// this is however, not currently implemented as said changes
// typically occur during editing and as such have little to no
// impact on the cpu optimization. live-coding may be affected,
// however, and further investigation there may be warranted.
/* gl_loc int array explanation:
......@@ -45,6 +49,10 @@ void preset_hub_store(t_preset_hub *h, t_float f);
void preset_hub_add_a_node(t_preset_hub *h, t_preset_node *x);
void preset_hub_delete_a_node(t_preset_hub *h, t_preset_node *x);
void preset_node_seek_hub(t_preset_node *x);
int preset_hub_compare_loc(int *h_loc, int h_loc_length, int *n_loc, int n_loc_length);
static int preset_node_location_changed(t_preset_node *x);
static void preset_node_update_my_glist_location(t_preset_node *x);
//======================== global vars =============================//
......@@ -58,7 +66,9 @@ t_glob_preset_hub_list *gphl;
int glob_preset_node_list_add(t_preset_node *x)
{
#ifdef PH_DEBUG
fprintf(stderr,"glob_preset_node_list_add\n");
#endif
t_glob_preset_node_list *n1, *n2;
if (!gpnl) {
......@@ -78,7 +88,9 @@ int glob_preset_node_list_add(t_preset_node *x)
int glob_preset_node_list_delete(t_preset_node *x)
{
#ifdef PH_DEBUG
fprintf(stderr,"glob_preset_node_list_delete\n");
#endif
t_glob_preset_node_list *n1, *n2;
int found;
......@@ -103,7 +115,9 @@ int glob_preset_node_list_delete(t_preset_node *x)
freebytes(n2, sizeof(*n2));
} else {
// we should never get here
#ifdef PH_DEBUG
fprintf(stderr,"error, could not find appropriate gpnl to delete\n");
#endif
return(1);
}
}
......@@ -113,7 +127,9 @@ int glob_preset_node_list_delete(t_preset_node *x)
int glob_preset_node_list_update_paired(t_preset_node *x, int paired)
{
#ifdef PH_DEBUG
fprintf(stderr,"glob_preset_node_list_update_paired %d\n", paired);
#endif
t_glob_preset_node_list *n;
if (!gpnl)
......@@ -129,7 +145,9 @@ int glob_preset_node_list_update_paired(t_preset_node *x, int paired)
}
else {
// we should never get here
#ifdef PH_DEBUG
fprintf(stderr,"error, could not find appropriate gpnl to pair\n");
#endif
return(1);
}
......@@ -138,13 +156,17 @@ int glob_preset_node_list_update_paired(t_preset_node *x, int paired)
void glob_preset_node_list_seek_hub(void)
{
#ifdef PH_DEBUG
fprintf(stderr,"glob_preset_node_list_seek_hub\n");
#endif
t_glob_preset_node_list *nl;
if (gpnl) {
nl = gpnl;
while(nl) {
#ifdef PH_DEBUG
fprintf(stderr," seeking\n");
#endif
if (!nl->gpnl_paired) {
preset_node_seek_hub(nl->gpnl_node);
}
......@@ -153,9 +175,58 @@ void glob_preset_node_list_seek_hub(void)
}
}
// this should be called whenever glist has been changed (tofront/back, cut, delete, undo/redo cut/delete)
void glob_preset_node_list_check_loc_and_update(void)
{
#ifdef PH_DEBUG
fprintf(stderr,"glob_preset_node_list_check_loc_and_update\n");
#endif
t_glob_preset_hub_list *hl;
t_preset_hub_data *hd;
int i = 0;
if (gphl) {
hl = gphl;
while(hl) {
#ifdef PH_DEBUG
fprintf(stderr," searching\n");
#endif
hd = hl->gphl_hub->ph_data;
while (hd) {
#ifdef PH_DEBUG
fprintf(stderr," checking data\n");
#endif
if (hd->phd_node) {
#ifdef PH_DEBUG
fprintf(stderr," node is active\n");
#endif
preset_node_update_my_glist_location(hd->phd_node);
if (preset_node_location_changed(hd->phd_node)) {
#ifdef PH_DEBUG
fprintf(stderr," location changed...adjusting length %d to %d\n", hd->phd_pn_gl_loc_length, hd->phd_node->pn_gl_loc_length);
#endif
hd->phd_pn_gl_loc_length = hd->phd_node->pn_gl_loc_length;
hd->phd_pn_gl_loc = (int*)realloc(hd->phd_pn_gl_loc, hd->phd_pn_gl_loc_length*sizeof(int));
for (i=0; i < hd->phd_pn_gl_loc_length; i++) {
#ifdef PH_DEBUG
fprintf(stderr," loc old:%d new:%d\n", hd->phd_pn_gl_loc[i], hd->phd_node->pn_gl_loc[i]);
#endif
hd->phd_pn_gl_loc[i] = hd->phd_node->pn_gl_loc[i];
}
}
}
hd = hd->phd_next;
}
hl = hl->gphl_next;
}
}
}
int glob_preset_hub_list_add(t_preset_hub *x)
{
#ifdef PH_DEBUG
fprintf(stderr,"glob_preset_hub_list_add\n");
#endif
t_glob_preset_hub_list *h1, *h2;
if (!gphl) {
......@@ -174,7 +245,9 @@ int glob_preset_hub_list_add(t_preset_hub *x)
int glob_preset_hub_list_delete(t_preset_hub *x)
{
#ifdef PH_DEBUG
fprintf(stderr,"glob_preset_hub_list_delete\n");
#endif
t_glob_preset_hub_list *h1, *h2;
int found;
......@@ -200,7 +273,9 @@ int glob_preset_hub_list_delete(t_preset_hub *x)
}
else {
// we should never get here
#ifdef PH_DEBUG
fprintf(stderr,"error, could not find appropriate gphl to delete\n");
#endif
return(1);
}
}
......@@ -216,7 +291,9 @@ int glob_preset_hub_list_delete(t_preset_hub *x)
static void preset_node_update_my_glist_location(t_preset_node *x)
{
#ifdef PH_DEBUG
fprintf(stderr,"node_update_glist_location\n");
#endif
// location is calculated in respect to the hub (if any), otherwise it is 0
t_preset_hub *h;
t_canvas *c = x->pn_canvas;
......@@ -236,9 +313,18 @@ static void preset_node_update_my_glist_location(t_preset_node *x)
int depth = 0;
while (!found && c) {
if (c->gl_phub) {
#ifdef PH_DEBUG
fprintf(stderr," gl_phub != NULL\n");
#endif
h = c->gl_phub;
while (h) {
if (!strcmp(c->gl_phub->ph_name->s_name, x->pn_hub_name->s_name)) {
#ifdef PH_DEBUG
fprintf(stderr," analyzing hub\n");
#endif
if (!strcmp(h->ph_name->s_name, x->pn_hub_name->s_name)) {
#ifdef PH_DEBUG
fprintf(stderr," found a match\n");
#endif
found = 1;
break;
}
......@@ -252,7 +338,9 @@ static void preset_node_update_my_glist_location(t_preset_node *x)
if (found) {
#ifdef PH_DEBUG
fprintf(stderr," depth = %d\n", depth);
#endif
// allocate depth array
x->pn_gl_loc = (int*)calloc(depth+1, sizeof(int));
......@@ -271,11 +359,15 @@ static void preset_node_update_my_glist_location(t_preset_node *x)
{
g = g->g_next;
i++;
#ifdef PH_DEBUG
fprintf(stderr," searching... %d\n", i);
#endif
}
// even if the g fails sanity check due to creation time, it will still land on the last created element whose
// pointer at this point is still null since this means this is being called at the end of the preset_node_new call
#ifdef PH_DEBUG
fprintf(stderr," location = %d %lx %lx\n", i, (t_int)g, (t_int)target);
#endif
x->pn_gl_loc[j] = i;
// now readjust the target, c, g, and i variables for the next level up
......@@ -288,13 +380,18 @@ static void preset_node_update_my_glist_location(t_preset_node *x)
}
x->pn_gl_loc_length = depth+1;
#ifdef PH_DEBUG
fprintf(stderr," final structure:\n");
for (j = 0; j < x->pn_gl_loc_length; j++) {
fprintf(stderr," %d: %d\n", j, x->pn_gl_loc[j]);
}
} else {
#endif
}
#ifdef PH_DEBUG
else {
fprintf(stderr," preset_node: no matching hub %s found\n", x->pn_hub_name->s_name);
}
#endif
// finally if this is the first time we are creating the object, old_location should be the same as the current location
if (x->pn_old_gl_loc_length == 0) {
......@@ -309,18 +406,24 @@ static void preset_node_update_my_glist_location(t_preset_node *x)
// nodes that have not been paired yet.
void preset_node_seek_hub(t_preset_node *x)
{
#ifdef PH_DEBUG
fprintf(stderr,"preset_node_seek_hub\n");
#endif
t_canvas *y = x->pn_canvas;
t_preset_hub *h;
if (!x->pn_hub) {
#ifdef PH_DEBUG
fprintf(stderr," have to seek\n");
#endif
while (!x->pn_hub && y) {
h = y->gl_phub;
while (h) {
if (h->ph_name->s_name == x->pn_hub_name->s_name) {
x->pn_hub = h;
#ifdef PH_DEBUG
fprintf(stderr," node found hub\n");
#endif
// update our location in respect to the newfound hub
preset_node_update_my_glist_location(x);
// add a node on the hub's list of nodes and copy location to its struct
......@@ -408,7 +511,9 @@ void preset_node_set_and_output_value(t_preset_node *x, t_atom *val)
static void *preset_node_new(t_symbol *s, int argc, t_atom *argv)
{
#ifdef PH_DEBUG
fprintf(stderr,"===preset_node_new===\n");
#endif
t_glist *glist=(t_glist *)canvas_getcurrent();
t_canvas *canvas = (t_canvas *)glist_getcanvas(glist);
......@@ -422,7 +527,6 @@ static void *preset_node_new(t_symbol *s, int argc, t_atom *argv)
// read basic creation arguments
x->pn_hub_name = (t_symbol *)atom_getsymbol(&argv[0]);
//fprintf(stderr,"hub name %s\n", x->pn_hub_name->s_name);
x->pn_canvas = canvas;
t_canvas *y = x->pn_canvas;
......@@ -521,7 +625,9 @@ typedef enum
void preset_hub_save(t_gobj *z, t_binbuf *b)
{
#ifdef PH_DEBUG
fprintf(stderr,"preset_hub_save\n");
#endif
int i;
t_preset_hub_data *phd;
t_node_preset *np;
......@@ -538,7 +644,9 @@ void preset_hub_save(t_gobj *z, t_binbuf *b)
phd = x->ph_data;
while (phd) {
#ifdef PH_DEBUG
fprintf(stderr," saving phd\n");
#endif
// designate a node and state whether it is active or disabled
// (disabled nodes are ones that have presets saved but have been deleted since--
// we keep these in the case of undo actions during the session that may go beyond
......@@ -563,7 +671,9 @@ void preset_hub_save(t_gobj *z, t_binbuf *b)
phd = phd->phd_next;
}
#ifdef PH_DEBUG
fprintf(stderr," done\n");
#endif
binbuf_addv(b, ";");
}
......@@ -576,7 +686,9 @@ void preset_hub_bang(t_preset_hub *x)
void preset_hub_recall(t_preset_hub *x, t_float f)
{
#ifdef PH_DEBUG
fprintf(stderr,"hub_recall\n");
#endif
t_atom ap[2];
t_preset_hub_data *hd;
t_node_preset *np;
......@@ -587,18 +699,28 @@ void preset_hub_recall(t_preset_hub *x, t_float f)
if (x->ph_data) {
hd = x->ph_data;
while (hd) {
#ifdef PH_DEBUG
fprintf(stderr," searching\n");
#endif
// now check if the object is active (node pointer is not NULL)
if (hd->phd_node) {
#ifdef PH_DEBUG
fprintf(stderr," object active\n");
#endif
if (hd->phd_npreset) {
#ifdef PH_DEBUG
fprintf(stderr," object has presets\n");
#endif
np = hd->phd_npreset;
while (np) {
#ifdef PH_DEBUG
fprintf(stderr," searching presets\n");
#endif
if (np->np_preset == (int)f) {
valid = 1;
#ifdef PH_DEBUG
fprintf(stderr," valid %d %g\n", (hd->phd_node ? 1:0), np->np_val.a_w.w_float);
#endif
preset_node_set_and_output_value(hd->phd_node, &np->np_val);
break;
}
......@@ -619,7 +741,9 @@ void preset_hub_recall(t_preset_hub *x, t_float f)
void preset_hub_store(t_preset_hub *x, t_float f)
{
#ifdef PH_DEBUG
fprintf(stderr,"preset_hub_store\n");
#endif
t_atom ap[1];
t_preset_hub_data *hd1;
t_node_preset *np1, *np2;
......@@ -634,9 +758,13 @@ void preset_hub_store(t_preset_hub *x, t_float f)
if (x->ph_data) {
hd1 = x->ph_data;
while (hd1) {
#ifdef PH_DEBUG
fprintf(stderr," analyzing phd\n");
#endif
if (hd1->phd_node) {
#ifdef PH_DEBUG
fprintf(stderr," node is active\n");
#endif
// only if the node is active (not NULL/disabled)
overwrite = 0;
if (hd1->phd_npreset) {
......@@ -678,6 +806,7 @@ void preset_hub_store(t_preset_hub *x, t_float f)
}
SETFLOAT(ap+0, f);
outlet_anything(x->ph_outlet, gensym("store"), 1, ap);
canvas_dirty(x->ph_canvas, 1);
}
}
......@@ -702,7 +831,9 @@ void preset_hub_add_a_node(t_preset_hub *h, t_preset_node *x)
hd1 = NULL;
hd2 = NULL;
#ifdef PH_DEBUG
fprintf(stderr,"preset_hub_add_a_node\n");
#endif
if (h->ph_data) {
// first check for disabled nodes and reenable them if they match location
hd1 = h->ph_data;
......@@ -712,7 +843,9 @@ void preset_hub_add_a_node(t_preset_hub *h, t_preset_node *x)
if (!preset_hub_compare_loc(hd1->phd_pn_gl_loc, hd1->phd_pn_gl_loc_length, x->pn_gl_loc, x->pn_gl_loc_length))
{
// if this hub node data's location matches that of the node
#ifdef PH_DEBUG
fprintf(stderr," found disabled -> enabling\n");
#endif
found = 1;
hd1->phd_node = x;
break;
......@@ -724,14 +857,18 @@ void preset_hub_add_a_node(t_preset_hub *h, t_preset_node *x)
if (!found) {
// we have no stored node data (or none that match node's location) so let's create a new one
#ifdef PH_DEBUG
fprintf(stderr," creating a new\n");
#endif
// create a new data struct
hd2 = (t_preset_hub_data *)t_getbytes(sizeof(*hd2));
// reconstruct the dynamic location array
hd2->phd_pn_gl_loc_length = x->pn_gl_loc_length;
hd2->phd_pn_gl_loc = (int*)calloc(hd2->phd_pn_gl_loc_length, sizeof(int));
for (i=0; i < hd2->phd_pn_gl_loc_length; i++) {
#ifdef PH_DEBUG
fprintf(stderr," loc %d\n", x->pn_gl_loc[i]);
#endif
hd2->phd_pn_gl_loc[i] = x->pn_gl_loc[i];
}
// assign node value
......@@ -755,14 +892,18 @@ void preset_hub_delete_a_node(t_preset_hub *h, t_preset_node *x)
t_preset_hub_data *hd1;
hd1 = NULL;
#ifdef PH_DEBUG
fprintf(stderr,"preset_hub_delete_a_node\n");
#endif
if (h->ph_data) {
// check for enabled nodes only
hd1 = h->ph_data;
while (hd1) {
if (hd1->phd_node && hd1->phd_node == x) {
// only if the node is enabled and matches ours
#ifdef PH_DEBUG
fprintf(stderr," found enabled -> disabling\n");
#endif
hd1->phd_node = NULL;
break;
}
......@@ -773,7 +914,9 @@ void preset_hub_delete_a_node(t_preset_hub *h, t_preset_node *x)
static void *preset_hub_new(t_symbol *s, int argc, t_atom *argv)
{
#ifdef PH_DEBUG
fprintf(stderr,"===preset_hub_new===\n");
#endif
t_glob_preset_node_list *nl;
t_glob_preset_hub_list *hl;
t_preset_hub_data *hd1, *hd2;
......@@ -832,7 +975,9 @@ static void *preset_hub_new(t_symbol *s, int argc, t_atom *argv)
}*/
pos++;
}
#ifdef PH_DEBUG
fprintf(stderr,"hub name %s invis %d\n", x->ph_name->s_name, (int)x->ph_invis);
#endif
pos++; // one more time to move ahead of the %hidden% tag
......@@ -866,22 +1011,32 @@ static void *preset_hub_new(t_symbol *s, int argc, t_atom *argv)
// load the data from the buffer and build the preset db
if (pos < argc) {
for (i=pos; i < argc; i++) {
#ifdef PH_DEBUG
fprintf(stderr," position: %d\n", i);
#endif
// SYMBOL ANALYSIS
if (argv[i].a_type == A_SYMBOL) {
#ifdef PH_DEBUG
fprintf(stderr," data = %s\n", atom_getsymbol(&argv[i])->s_name);
#endif
if (!strcmp(atom_getsymbol(&argv[i])->s_name, "%node%")) {
// beginning of a new node
#ifdef PH_DEBUG
fprintf(stderr," new node\n");
#endif
hd2 = (t_preset_hub_data *)t_getbytes(sizeof(*hd2));
hd2->phd_pn_gl_loc_length = 0;
if (hd1) {
hd1->phd_next = hd2;
fprintf(stderr," new node\n");
#ifdef PH_DEBUG
fprintf(stderr," not first node\n");
#endif
}
else {
x->ph_data = hd2;
#ifdef PH_DEBUG
fprintf(stderr," first node\n");
#endif
}
hd1 = hd2;
np1 = NULL; // have to reset it so that new presets are not erroneously appended to previous node
......@@ -889,28 +1044,38 @@ static void *preset_hub_new(t_symbol *s, int argc, t_atom *argv)
}
else if (!strcmp(atom_getsymbol(&argv[i])->s_name, "%preset%")) {
// beginning of a new preset
#ifdef PH_DEBUG
fprintf(stderr," new preset\n");
#endif
np2 = (t_node_preset *)t_getbytes(sizeof(*np2));
if (np1) {
np1->np_next = np2;
fprintf(stderr," new preset\n");
#ifdef PH_DEBUG
fprintf(stderr," not first preset\n");
#endif
}
else {
hd2->phd_npreset = np2;
#ifdef PH_DEBUG
fprintf(stderr," first preset\n");
#endif
}
np1 = np2;
h_cur = H_PRESET;
}
// SYMBOL DATA
else if (h_cur == H_PRESET_DATA) {
#ifdef PH_DEBUG
fprintf(stderr," sym data %s\n", atom_getsymbol(&argv[i])->s_name);
#endif
SETSYMBOL(&np2->np_val, atom_getsymbol(&argv[i]));
}
}
// FLOAT ANALYSIS
else if (argv[i].a_type == A_FLOAT) {
#ifdef PH_DEBUG
fprintf(stderr," data = %g\n", atom_getfloat(&argv[i]));
#endif
if (h_cur == H_NODE) {
// node location
hd2->phd_pn_gl_loc_length++;
......@@ -919,16 +1084,22 @@ static void *preset_hub_new(t_symbol *s, int argc, t_atom *argv)
hd2->phd_pn_gl_loc = (int*)calloc(1, sizeof(int));
else hd2->phd_pn_gl_loc = (int*)realloc(hd2->phd_pn_gl_loc, hd2->phd_pn_gl_loc_length*sizeof(int));
hd2->phd_pn_gl_loc[hd2->phd_pn_gl_loc_length-1] = (int)atom_getfloat(&argv[i]);
#ifdef PH_DEBUG
fprintf(stderr," loc = %d\n", hd2->phd_pn_gl_loc[hd2->phd_pn_gl_loc_length-1]);
#endif
}
else if (h_cur == H_PRESET) {
// preset number
#ifdef PH_DEBUG
fprintf(stderr," preset %g\n", atom_getfloat(&argv[i]));
#endif
np2->np_preset = (int)atom_getfloat(&argv[i]);
h_cur = H_PRESET_DATA;
}
else if (h_cur == H_PRESET_DATA) {
#ifdef PH_DEBUG
fprintf(stderr," preset data %g\n", atom_getfloat(&argv[i]));
#endif
SETFLOAT(&np2->np_val, atom_getfloat(&argv[i]));
}
}
......@@ -949,7 +1120,9 @@ static void *preset_hub_new(t_symbol *s, int argc, t_atom *argv)
static void preset_hub_free(t_preset_hub* x)
{
#ifdef PH_DEBUG
fprintf(stderr,"preset_hub_free\n");
#endif
t_glob_preset_node_list *nl;
t_preset_hub_data *hd1, *hd2;
t_node_preset *np1, *np2;
......@@ -957,15 +1130,21 @@ static void preset_hub_free(t_preset_hub* x)
// inform all nodes that the hub is going bye-bye
if (gpnl) {
#ifdef PH_DEBUG
fprintf(stderr," we got gpnl\n");
#endif
nl = gpnl;
while(nl) {
#ifdef PH_DEBUG
fprintf(stderr," analyzing gpnl entry %d\n", nl->gpnl_paired);
#endif
if (nl->gpnl_paired && nl->gpnl_node->pn_hub == x) {
// we only make the hub pointer null and leave location for undo/redo/save purposes
nl->gpnl_paired = 0;
nl->gpnl_node->pn_hub = NULL;
#ifdef PH_DEBUG
fprintf(stderr," removed gpnl reference\n");