36 |
return NULL; |
return NULL; |
37 |
} |
} |
38 |
|
|
39 |
static void undo_object_free(undo_object_t *obj) { |
static void undo_object_free(object_t *obj) { |
40 |
char *msg = osm_object_string(obj->type, obj->data.ptr); |
char *msg = osm_object_string(obj); |
41 |
printf(" object %s\n", msg); |
printf(" object %s\n", msg); |
42 |
g_free(msg); |
g_free(msg); |
43 |
|
|
44 |
if(obj->data.ptr) { |
if(obj->ptr) { |
45 |
switch(obj->type) { |
switch(obj->type) { |
46 |
case NODE: |
case NODE: |
47 |
osm_node_free(NULL, obj->data.node); |
osm_node_free(NULL, obj->node); |
48 |
break; |
break; |
49 |
|
|
50 |
case WAY: |
case WAY: |
51 |
osm_way_free(obj->data.way); |
osm_way_free(obj->way); |
52 |
break; |
break; |
53 |
|
|
54 |
default: |
default: |
55 |
printf("ERROR: unsupported object %s\n", |
printf("ERROR: unsupported object %s\n", |
56 |
osm_type_string(obj->type)); |
osm_object_type_string(obj)); |
57 |
g_assert(0); |
g_assert(0); |
58 |
break; |
break; |
59 |
} |
} |
121 |
} |
} |
122 |
|
|
123 |
/* create a local copy of the entire object */ |
/* create a local copy of the entire object */ |
124 |
static undo_object_t *undo_object_copy(type_t type, void *object) { |
static object_t *undo_object_copy(object_t *object) { |
125 |
switch(type) { |
switch(object->type) { |
126 |
case NODE: { |
case NODE: { |
127 |
undo_object_t *ob = g_new0(undo_object_t, 1); |
object_t *ob = g_new0(object_t, 1); |
128 |
ob->type = type; |
ob->type = object->type; |
129 |
|
|
130 |
/* fields ignored in this copy operation: */ |
/* fields ignored in this copy operation: */ |
131 |
/* ways, icon_buf, map_item_chain, next */ |
/* ways, icon_buf, map_item_chain, next */ |
132 |
|
|
133 |
node_t *node = (node_t*)object; |
ob->node = g_new0(node_t, 1); |
|
ob->data.node = g_new0(node_t, 1); |
|
134 |
/* copy all important parts, omitting icon pointers etc. */ |
/* copy all important parts, omitting icon pointers etc. */ |
135 |
ob->data.node->id = node->id; |
ob->node->id = object->node->id; |
136 |
ob->data.node->lpos = node->lpos; |
ob->node->lpos = object->node->lpos; |
137 |
ob->data.node->pos = node->pos; |
ob->node->pos = object->node->pos; |
138 |
/* user is a pointer, but since the users list */ |
/* user is a pointer, but since the users list */ |
139 |
/* is never touched it's ok */ |
/* is never touched it's ok */ |
140 |
ob->data.node->user = node->user; |
ob->node->user = object->node->user; |
141 |
ob->data.node->visible = node->visible; |
ob->node->visible = object->node->visible; |
142 |
ob->data.node->time = node->time; |
ob->node->time = object->node->time; |
143 |
ob->data.node->tag = osm_tags_copy(node->tag, FALSE); |
ob->node->tag = osm_tags_copy(object->node->tag, FALSE); |
144 |
ob->data.node->flags = node->flags; |
ob->node->flags = object->node->flags; |
145 |
ob->data.node->zoom_max = node->zoom_max; |
ob->node->zoom_max = object->node->zoom_max; |
146 |
|
|
147 |
return ob; |
return ob; |
148 |
} break; |
} break; |
149 |
|
|
150 |
case WAY: { |
case WAY: { |
151 |
undo_object_t *ob = g_new0(undo_object_t, 1); |
object_t *ob = g_new0(object_t, 1); |
152 |
ob->type = type; |
ob->type = object->type; |
153 |
|
|
154 |
/* fields ignored in this copy operation: */ |
/* fields ignored in this copy operation: */ |
155 |
|
|
156 |
way_t *way = (way_t*)object; |
ob->way = g_new0(way_t, 1); |
|
ob->data.way = g_new0(way_t, 1); |
|
157 |
/* copy all important parts */ |
/* copy all important parts */ |
158 |
ob->data.way->id = way->id; |
ob->way->id = object->way->id; |
159 |
/* user is a pointer, but since the users list */ |
/* user is a pointer, but since the users list */ |
160 |
/* is never touched it's ok */ |
/* is never touched it's ok */ |
161 |
ob->data.way->user = way->user; |
ob->way->user = object->way->user; |
162 |
ob->data.way->visible = way->visible; |
ob->way->visible = object->way->visible; |
163 |
ob->data.way->time = way->time; |
ob->way->time = object->way->time; |
164 |
ob->data.way->tag = osm_tags_copy(way->tag, FALSE); |
ob->way->tag = osm_tags_copy(object->way->tag, FALSE); |
165 |
ob->data.way->flags = way->flags; |
ob->way->flags = object->way->flags; |
166 |
|
|
167 |
return ob; |
return ob; |
168 |
} break; |
} break; |
169 |
|
|
170 |
default: |
default: |
171 |
printf("UNDO WARNING: ignoring unsupported object %s\n", |
printf("UNDO WARNING: ignoring unsupported object %s\n", |
172 |
osm_type_string(type)); |
osm_object_type_string(object)); |
173 |
break; |
break; |
174 |
} |
} |
175 |
|
|
176 |
return NULL; |
return NULL; |
177 |
} |
} |
178 |
|
|
179 |
void undo_remember_delete(appdata_t *appdata, type_t type, |
void undo_remember_delete(appdata_t *appdata, object_t *object) { |
|
void *object) { |
|
180 |
|
|
181 |
/* don't do anything if undo isn't enabled */ |
/* don't do anything if undo isn't enabled */ |
182 |
if(!appdata->menu_item_osm_undo) |
if(!appdata->menu_item_osm_undo) |
183 |
return; |
return; |
184 |
|
|
185 |
printf("UNDO: remembering delete operation for %s\n", |
printf("UNDO: remembering delete operation for %s\n", |
186 |
osm_type_string(type)); |
osm_object_type_string(object)); |
187 |
|
|
188 |
/* create a new undo state */ |
/* create a new undo state */ |
189 |
undo_state_t *state = undo_append_state(appdata); |
undo_state_t *state = undo_append_state(appdata); |
193 |
/* operation on the database/map so only one undo_op is saved */ |
/* operation on the database/map so only one undo_op is saved */ |
194 |
undo_op_t *op = state->op = g_new0(undo_op_t, 1); |
undo_op_t *op = state->op = g_new0(undo_op_t, 1); |
195 |
op->type = UNDO_DELETE; |
op->type = UNDO_DELETE; |
196 |
op->object = undo_object_copy(type, object); |
op->object = undo_object_copy(object); |
197 |
} |
} |
198 |
|
|
199 |
/* undo the deletion of an object */ |
/* undo the deletion of an object */ |
200 |
static void undo_operation_object_delete(appdata_t *appdata, |
static void undo_operation_object_delete(appdata_t *appdata, object_t *obj) { |
|
undo_object_t *obj) { |
|
201 |
|
|
202 |
char *msg = osm_object_string(obj->type, obj->data.ptr); |
char *msg = osm_object_string(obj); |
203 |
printf("UNDO deletion of object %s\n", msg); |
printf("UNDO deletion of object %s\n", msg); |
204 |
g_free(msg); |
g_free(msg); |
205 |
|
|
206 |
switch(obj->type) { |
switch(obj->type) { |
207 |
case NODE: { |
case NODE: { |
|
node_t *node = obj->data.node; |
|
|
|
|
208 |
/* there must be an "deleted" entry which needs to be */ |
/* there must be an "deleted" entry which needs to be */ |
209 |
/* removed */ |
/* removed */ |
210 |
node_t *orig = osm_get_node_by_id(appdata->osm, node->id); |
node_t *orig = osm_get_node_by_id(appdata->osm, obj->node->id); |
211 |
g_assert(orig); |
g_assert(orig); |
212 |
g_assert(orig->flags & OSM_FLAG_DELETED); |
g_assert(orig->flags & OSM_FLAG_DELETED); |
213 |
way_chain_t *wchain = |
way_chain_t *wchain = |
215 |
g_assert(!wchain); |
g_assert(!wchain); |
216 |
|
|
217 |
/* then restore old node */ |
/* then restore old node */ |
218 |
osm_node_dump(node); |
osm_node_dump(obj->node); |
219 |
osm_node_restore(appdata->osm, node); |
osm_node_restore(appdata->osm, obj->node); |
220 |
josm_elemstyles_colorize_node(appdata->map->style, node); |
josm_elemstyles_colorize_node(appdata->map->style, obj->node); |
221 |
map_node_draw(appdata->map, node); |
map_node_draw(appdata->map, obj->node); |
222 |
obj->data.ptr = NULL; |
obj->ptr = NULL; |
223 |
} break; |
} break; |
224 |
|
|
225 |
default: |
default: |