Freeciv-3.1: /fast/freeciv/nightly/S3_1/client/gui-gtk-3.0/editprop.c Source File

Freeciv-3.1

Loading...
Searching...
No Matches
editprop.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 2005 - The Freeciv Project
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <limits.h> /* USHRT_MAX */
19
20#include <gtk/gtk.h>
21#include <gdk/gdkkeysyms.h>
22
23/* utility */
24#include "bitvector.h"
25#include "fc_cmdline.h"
26#include "fcintl.h"
27#include "log.h"
28#include "mem.h"
29
30/* common */
31#include "fc_interface.h"
32#include "game.h"
33#include "government.h"
34#include "map.h"
35#include "movement.h"
36#include "research.h"
37#include "tile.h"
38
39/* client */
40#include "client_main.h"
41#include "climisc.h"
42#include "editor.h"
43#include "mapview_common.h"
44#include "tilespec.h"
45
46/* client/gui-gtk-3.0 */
47#include "canvas.h"
48#include "gui_main.h"
49#include "gui_stuff.h"
50#include "plrdlg.h"
51#include "sprite.h"
52
53#include "editprop.h"
54
55
56/* Forward declarations. */
57struct objprop;
58struct objbind;
59struct property_page;
60struct property_editor;
61struct extviewer;
62
63/****************************************************************************
64 Miscellaneous helpers.
65****************************************************************************/
66static GdkPixbuf *create_pixbuf_from_layers(const struct tile *ptile,
67 const struct unit *punit,
68 const struct city *pcity,
69 enum layer_category category);
70static GdkPixbuf *create_tile_pixbuf(const struct tile *ptile);
71static GdkPixbuf *create_unit_pixbuf(const struct unit *punit);
72static GdkPixbuf *create_city_pixbuf(const struct city *pcity);
73
74static void add_column(GtkWidget *view,
75 int col_id,
76 const char *name,
77 GType gtype,
78 bool editable,
79 bool is_radio,
80 GCallback edit_callback,
81 gpointer callback_userdata);
82
83static bool can_create_unit_at_tile(struct tile *ptile);
84
85static int get_next_unique_tag(void);
86
87/* 'struct stored_tag_hash' and related functions. */
88#define SPECHASH_TAG stored_tag
89#define SPECHASH_INT_KEY_TYPE
90#define SPECHASH_INT_DATA_TYPE
91#include "spechash.h"
92
93/* NB: If packet definitions change, be sure to
94 * update objbind_pack_current_values()!!! */
95 union packetdata {
96 struct {
97 gpointer v_pointer1;
98 gpointer v_pointer2;
99 } pointers;
100 struct packet_edit_tile *tile;
101 struct packet_edit_startpos_full *startpos;
102 struct packet_edit_city *city;
103 struct packet_edit_unit *unit;
104 struct packet_edit_player *player;
105 struct {
106 struct packet_edit_game *game;
107 struct packet_edit_scenario_desc *desc;
108 } game;
109};
110
111/* Helpers for the OPID_TILE_VISION property. */
112 struct tile_vision_data {
113 bv_player tile_known, tile_seen[V_COUNT];
114};
115const char *vision_layer_get_name(enum vision_layer);
116
117#define PF_MAX_CLAUSES 16
118#define PF_DISJUNCTION_SEPARATOR "|"
119#define PF_CONJUNCTION_SEPARATOR "&"
120
121 struct pf_pattern {
122 bool negate;
123 char *text;
124};
125
126 struct pf_conjunction {
127 struct pf_pattern conjunction[PF_MAX_CLAUSES];
128 int count;
129};
130
131 struct property_filter {
132 struct pf_conjunction disjunction[PF_MAX_CLAUSES];
133 int count;
134};
135
136static struct property_filter *property_filter_new(const char *filter);
137static bool property_filter_match(struct property_filter *pf,
138 const struct objprop *op);
139static void property_filter_free(struct property_filter *pf);
140
141
142/****************************************************************************
143 Object type declarations.
144
145 To add a new object type:
146 1. Add a value in enum editor_object_type in client/editor.h.
147 2. Add a string name to objtype_get_name.
148 3. Add code in objtype_get_id_from_object.
149 4. Add code in objtype_get_object_from_id.
150 5. Add a case handler in objtype_is_conserved, and if
151 the object type is not conserved, then also in
152 objbind_request_destroy_object and property_page_create_objects.
153 6. Add an if-block in objbind_get_value_from_object.
154 7. Add an if-block in objbind_get_allowed_value_span.
155 9. Add a case handler in property_page_setup_objprops.
156 10. Add a case handler in property_page_add_objbinds_from_tile
157 if applicable.
158
159 Furthermore, if the object type is to be editable:
160 11. Define its edit packet in common/networking/packets.def.
161 12. Add the packet handler in server/edithand.c.
162 13. Add its edit packet type to union packetdata.
163 14. Add an if-block in objbind_pack_current_values.
164 15. Add an if-block in objbind_pack_modified_value.
165 16. Add code in property_page_new_packet.
166 17. Add code in property_page_send_packet.
167 18. Add calls to editgui_notify_object_changed in
168 client/packhand.c or where applicable.
169
170****************************************************************************/
171
172/* OBJTYPE_* enum values defined in client/editor.h */
173
174static const char *objtype_get_name(enum editor_object_type objtype);
175static int objtype_get_id_from_object(enum editor_object_type objtype,
176 gpointer object);
177static gpointer objtype_get_object_from_id(enum editor_object_type objtype,
178 int id);
179static bool objtype_is_conserved(enum editor_object_type objtype);
180
181
182/****************************************************************************
183 Value type declarations.
184
185 To add a new value type:
186 1. Add a value in enum value_types.
187 2. Add its field in union propval_data.
188 3. Add a case handler in valtype_get_name.
189 4. Add a case handler in propval_copy if needed.
190 5. Add a case handler in propval_free if needed.
191 6. Add a case handler in propval_equal if needed.
192 7. Add a case handler in objprop_get_gtype.
193 8. Add a case handler in property_page_set_store_value.
194 9. Add a case handler in propval_as_string if needed.
195****************************************************************************/
196 enum value_types {
197 VALTYPE_NONE = 0,
198 VALTYPE_INT,
199 VALTYPE_BOOL,
200 VALTYPE_STRING,
201 VALTYPE_PIXBUF,
202 VALTYPE_BUILT_ARRAY, /* struct built_status[B_LAST] */
203 VALTYPE_INVENTIONS_ARRAY, /* bool[A_LAST] */
204 VALTYPE_BV_SPECIAL,
205 VALTYPE_BV_ROADS,
206 VALTYPE_BV_BASES,
207 VALTYPE_NATION,
208 VALTYPE_NATION_HASH, /* struct nation_hash */
209 VALTYPE_GOV,
210 VALTYPE_TILE_VISION_DATA /* struct tile_vision_data */
211};
212
213static const char *valtype_get_name(enum value_types valtype);
214
215
216/****************************************************************************
217 Propstate and propval declarations.
218
219 To add a new member to union propval_data, see the steps for adding a
220 new value type above.
221
222 New property values are "constructed" by objbind_get_value_from_object().
223****************************************************************************/
224 union propval_data {
225 gpointer v_pointer;
226 int v_int;
227 bool v_bool;
228 char *v_string;
229 const char *v_const_string;
230 GdkPixbuf *v_pixbuf;
231 struct built_status *v_built;
232 bv_max_extras v_bv_special;
233 bv_max_extras v_bv_roads;
234 bv_max_extras v_bv_bases;
235 struct nation_type *v_nation;
236 struct nation_hash *v_nation_hash;
237 struct government *v_gov;
238 bv_techs v_bv_inventions;
239 struct tile_vision_data *v_tile_vision;
240};
241
242 struct propval {
243 union propval_data data;
244 enum value_types valtype;
245 bool must_free;
246};
247
248static void propval_free(struct propval *pv);
249static void propval_free_data(struct propval *pv);
250static struct propval *propval_copy(struct propval *pv);
251static bool propval_equal(struct propval *pva, struct propval *pvb);
252
253 struct propstate {
254 int property_id;
255 struct propval *property_value;
256};
257
258static struct propstate *propstate_new(struct objprop *op,
259 struct propval *pv);
260static void propstate_destroy(struct propstate *ps);
261static void propstate_clear_value(struct propstate *ps);
262static void propstate_set_value(struct propstate *ps,
263 struct propval *pv);
264static struct propval *propstate_get_value(struct propstate *ps);
265
266#define SPECHASH_TAG propstate
267#define SPECHASH_INT_KEY_TYPE
268#define SPECHASH_IDATA_TYPE struct propstate *
269#define SPECHASH_IDATA_FREE propstate_destroy
270#include "spechash.h"
271
272
273/****************************************************************************
274 Objprop declarations.
275
276 To add a new object property:
277 1. Add a value in enum object_property_ids (grouped by
278 object type).
279 2. Define the property in property_page_setup_objprops.
280 3. Add a case handler in objbind_get_value_from_object
281 in the appropriate object type block.
282 4. Add a case handler in objprop_setup_widget.
283 5. Add a case handler in objprop_refresh_widget.
284
285 Furthermore, if the property is editable:
286 5. Add a field for this property in the edit
287 packet for this object type in common/networking/packets.def.
288 6. Add a case handler in objbind_pack_modified_value.
289 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
290 !!! 7. Add code to set the packet field in !!!
291 !!! objbind_pack_current_values(). !!!
292 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
293 8. Add code to handle changes in the packet field in
294 server/edithand.c handle_edit_<objtype>.
295
296 If the property makes use of an extviewer:
297 9. Handle widget creation in extviewer_new.
298 10. Handle refresh in extviewer_refresh_widgets.
299 11. Handle clear in extviewer_clear_widgets.
300 12. Handle any signal callbacks (e.g. toggled) if needed.
301
302 TODO: Add more object properties.
303****************************************************************************/
304 enum object_property_ids {
305 OPID_TILE_IMAGE,
306 OPID_TILE_X,
307 OPID_TILE_Y,
308 OPID_TILE_NAT_X,
309 OPID_TILE_NAT_Y,
310 OPID_TILE_CONTINENT,
311#ifdef FREECIV_DEBUG
312 OPID_TILE_ADDRESS,
313#endif /* FREECIV_DEBUG */
314 OPID_TILE_TERRAIN,
315 OPID_TILE_INDEX,
316 OPID_TILE_XY,
317 OPID_TILE_RESOURCE,
318 OPID_TILE_SPECIALS,
319 OPID_TILE_ROADS,
320 OPID_TILE_BASES,
321 OPID_TILE_VISION, /* tile_known and tile_seen */
322 OPID_TILE_LABEL,
323
324 OPID_STARTPOS_IMAGE,
325 OPID_STARTPOS_XY,
326 OPID_STARTPOS_EXCLUDE,
327 OPID_STARTPOS_NATIONS,
328
329 OPID_UNIT_IMAGE,
330#ifdef FREECIV_DEBUG
331 OPID_UNIT_ADDRESS,
332#endif /* FREECIV_DEBUG */
333 OPID_UNIT_TYPE,
334 OPID_UNIT_ID,
335 OPID_UNIT_XY,
336 OPID_UNIT_MOVES_LEFT,
337 OPID_UNIT_FUEL,
338 OPID_UNIT_MOVED,
339 OPID_UNIT_DONE_MOVING,
340 OPID_UNIT_HP,
341 OPID_UNIT_VETERAN,
342 OPID_UNIT_STAY,
343
344 OPID_CITY_IMAGE,
345 OPID_CITY_NAME,
346#ifdef FREECIV_DEBUG
347 OPID_CITY_ADDRESS,
348#endif /* FREECIV_DEBUG */
349 OPID_CITY_ID,
350 OPID_CITY_XY,
351 OPID_CITY_SIZE,
352 OPID_CITY_HISTORY,
353 OPID_CITY_BUILDINGS,
354 OPID_CITY_FOOD_STOCK,
355 OPID_CITY_SHIELD_STOCK,
356
357 OPID_PLAYER_NAME,
358 OPID_PLAYER_NATION,
359 OPID_PLAYER_GOV,
360 OPID_PLAYER_AGE,
361#ifdef FREECIV_DEBUG
362 OPID_PLAYER_ADDRESS,
363#endif /* FREECIV_DEBUG */
364 OPID_PLAYER_INVENTIONS,
365 OPID_PLAYER_SCENARIO_RESERVED,
366 OPID_PLAYER_SCIENCE,
367 OPID_PLAYER_GOLD,
368
369 OPID_GAME_SCENARIO,
370 OPID_GAME_SCENARIO_NAME,
371 OPID_GAME_SCENARIO_AUTHORS,
372 OPID_GAME_SCENARIO_DESC,
373 OPID_GAME_SCENARIO_RANDSTATE,
374 OPID_GAME_SCENARIO_PLAYERS,
375 OPID_GAME_STARTPOS_NATIONS,
376 OPID_GAME_PREVENT_CITIES,
377 OPID_GAME_LAKE_FLOODING,
378 OPID_GAME_RULESET_LOCKED
379};
380
381 enum object_property_flags {
382 OPF_NO_FLAGS = 0,
383 OPF_EDITABLE = 1 << 0,
384 OPF_IN_LISTVIEW = 1 << 1,
385 OPF_HAS_WIDGET = 1 << 2
386};
387
388 struct objprop {
389 int id;
390 const char *name;
391 const char *tooltip;
392 enum object_property_flags flags;
393 enum value_types valtype;
394 int column_id;
395 GtkTreeViewColumn *view_column;
396 GtkWidget *widget;
397 struct extviewer *extviewer;
398 struct property_page *parent_page;
399};
400
401static struct objprop *objprop_new(int id,
402 const char *name,
403 const char *tooltip,
404 enum object_property_flags flags,
405 enum value_types valtype,
406 struct property_page *parent);
407static int objprop_get_id(const struct objprop *op);
408static const char *objprop_get_name(const struct objprop *op);
409static const char *objprop_get_tooltip(const struct objprop *op);
410static enum value_types objprop_get_valtype(const struct objprop *op);
411static struct property_page *
412 objprop_get_property_page(const struct objprop *op);
413
414static bool objprop_show_in_listview(const struct objprop *op);
415static bool objprop_is_sortable(const struct objprop *op);
416static bool objprop_is_readonly(const struct objprop *op);
417static bool objprop_has_widget(const struct objprop *op);
418
419static GType objprop_get_gtype(const struct objprop *op);
420static const char *objprop_get_attribute_type_string(const struct objprop *op);
421static void objprop_set_column_id(struct objprop *op, int col_id);
422static int objprop_get_column_id(const struct objprop *op);
423static void objprop_set_treeview_column(struct objprop *op,
424 GtkTreeViewColumn *col);
425static GtkTreeViewColumn *objprop_get_treeview_column(const struct objprop *op);
426static GtkCellRenderer *objprop_create_cell_renderer(const struct objprop *op);
427
428static void objprop_setup_widget(struct objprop *op);
429static GtkWidget *objprop_get_widget(struct objprop *op);
430static void objprop_set_child_widget(struct objprop *op,
431 const char *widget_name,
432 GtkWidget *widget);
433static GtkWidget *objprop_get_child_widget(struct objprop *op,
434 const char *widget_name);
435static void objprop_set_extviewer(struct objprop *op,
436 struct extviewer *ev);
437static struct extviewer *objprop_get_extviewer(struct objprop *op);
438static void objprop_refresh_widget(struct objprop *op,
439 struct objbind *ob);
440static void objprop_widget_entry_changed(GtkEntry *entry, gpointer userdata);
441static void objprop_widget_spin_button_changed(GtkSpinButton *spin,
442 gpointer userdata);
443static void objprop_widget_toggle_button_changed(GtkToggleButton *button,
444 gpointer userdata);
445
446#define SPECHASH_TAG objprop
447#define SPECHASH_INT_KEY_TYPE
448#define SPECHASH_IDATA_TYPE struct objprop *
449#include "spechash.h"
450
451
452/****************************************************************************
453 Objbind declarations.
454****************************************************************************/
455 struct objbind {
456 enum editor_object_type objtype;
457 int object_id;
458 struct property_page *parent_property_page;
459 struct propstate_hash *propstate_table;
460 GtkTreeRowReference *rowref;
461};
462
463static struct objbind *objbind_new(enum editor_object_type objtype,
464 gpointer object);
465static void objbind_destroy(struct objbind *ob);
466static enum editor_object_type objbind_get_objtype(const struct objbind *ob);
467static void objbind_bind_properties(struct objbind *ob,
468 struct property_page *pp);
469static gpointer objbind_get_object(struct objbind *ob);
470static int objbind_get_object_id(struct objbind *ob);
471static void objbind_request_destroy_object(struct objbind *ob);
472static struct propval *objbind_get_value_from_object(struct objbind *ob,
473 struct objprop *op);
474static bool objbind_get_allowed_value_span(struct objbind *ob,
475 struct objprop *op,
476 double *pmin,
477 double *pmax,
478 double *pstep,
479 double *pbig_step);
480static bool objbind_set_modified_value(struct objbind *ob,
481 struct objprop *op,
482 struct propval *pv);
483static struct propval *objbind_get_modified_value(struct objbind *ob,
484 struct objprop *op);
485static void objbind_clear_modified_value(struct objbind *ob,
486 struct objprop *op);
487static bool objbind_property_is_modified(struct objbind *ob,
488 struct objprop *op);
489static bool objbind_has_modified_properties(struct objbind *ob);
490static void objbind_clear_all_modified_values(struct objbind *ob);
491static void objbind_pack_current_values(struct objbind *ob,
492 union packetdata packet);
493static void objbind_pack_modified_value(struct objbind *ob,
494 struct objprop *op,
495 union packetdata packet);
496static void objbind_set_rowref(struct objbind *ob,
497 GtkTreeRowReference *rr);
498static GtkTreeRowReference *objbind_get_rowref(struct objbind *ob);
499
500#define SPECHASH_TAG objbind
501#define SPECHASH_INT_KEY_TYPE
502#define SPECHASH_IDATA_TYPE struct objbind *
503#define SPECHASH_IDATA_FREE objbind_destroy
504#include "spechash.h"
505
506
507/****************************************************************************
508 Extended property viewer declarations. This is a set of widgets used
509 for viewing and/or editing properties with complex values (e.g. arrays).
510****************************************************************************/
511 struct extviewer {
512 struct objprop *objprop;
513 struct propval *pv_cached;
514
515 GtkWidget *panel_widget;
516 GtkWidget *panel_label;
517 GtkWidget *panel_button;
518 GtkWidget *panel_image;
519
520 GtkWidget *view_widget;
521 GtkWidget *view_label;
522
523 GtkListStore *store;
524 GtkTextBuffer *textbuf;
525};
526
527static struct extviewer *extviewer_new(struct objprop *op);
528static struct objprop *extviewer_get_objprop(struct extviewer *ev);
529static GtkWidget *extviewer_get_panel_widget(struct extviewer *ev);
530static GtkWidget *extviewer_get_view_widget(struct extviewer *ev);
531static void extviewer_refresh_widgets(struct extviewer *ev,
532 struct propval *pv);
533static void extviewer_clear_widgets(struct extviewer *ev);
534static void extviewer_panel_button_clicked(GtkButton *button,
535 gpointer userdata);
536static void extviewer_view_cell_toggled(GtkCellRendererToggle *cell,
537 gchar *path,
538 gpointer userdata);
539static void extviewer_textbuf_changed(GtkTextBuffer *textbuf,
540 gpointer userdata);
541
542
543/****************************************************************************
544 Property page declarations.
545****************************************************************************/
546 struct property_page {
547 enum editor_object_type objtype;
548
549 GtkWidget *widget;
550 GtkListStore *object_store;
551 GtkWidget *object_view;
552 GtkWidget *extviewer_notebook;
553
554 struct property_editor *pe_parent;
555
556 struct objprop_hash *objprop_table;
557 struct objbind_hash *objbind_table;
558 struct stored_tag_hash *tag_table;
559
560 struct objbind *focused_objbind;
561};
562
563static struct property_page *
564 property_page_new(enum editor_object_type objtype,
565 struct property_editor *parent);
566static void property_page_setup_objprops(struct property_page *pp);
567static const char *property_page_get_name(const struct property_page *pp);
568static enum editor_object_type
569 property_page_get_objtype(const struct property_page *pp);
570static void property_page_load_tiles(struct property_page *pp,
571 const struct tile_list *tiles);
572static void property_page_add_objbinds_from_tile(struct property_page *pp,
573 const struct tile *ptile);
574static int property_page_get_num_objbinds(const struct property_page *pp);
575static void property_page_clear_objbinds(struct property_page *pp);
576static void property_page_add_objbind(struct property_page *pp,
577 gpointer object_data);
578static void property_page_fill_widgets(struct property_page *pp);
579static struct objbind *
580 property_page_get_focused_objbind(struct property_page *pp);
581static void property_page_set_focused_objbind(struct property_page *pp,
582 struct objbind *ob);
583static struct objbind *property_page_get_objbind(struct property_page *pp,
584 int object_id);
585static void property_page_selection_changed(GtkTreeSelection *sel,
586 gpointer userdata);
587static gboolean property_page_selection_func(GtkTreeSelection *sel,
588 GtkTreeModel *model,
589 GtkTreePath *path,
590 gboolean currently_selected,
591 gpointer data);
592static void property_page_quick_find_entry_changed(GtkWidget *entry,
593 gpointer userdata);
594static void property_page_change_value(struct property_page *pp,
595 struct objprop *op,
596 struct propval *pv);
597static void property_page_send_values(struct property_page *pp);
598static void property_page_reset_objbinds(struct property_page *pp);
599static void property_page_destroy_objects(struct property_page *pp);
600static void property_page_create_objects(struct property_page *pp,
601 struct tile_list *hint_tiles);
602static union packetdata property_page_new_packet(struct property_page *pp);
603static void property_page_send_packet(struct property_page *pp,
604 union packetdata packet);
605static void property_page_free_packet(struct property_page *pp,
606 union packetdata packet);
607static void property_page_object_changed(struct property_page *pp,
608 int object_id,
609 bool remove);
610static void property_page_object_created(struct property_page *pp,
611 int tag, int object_id);
612static void property_page_add_extviewer(struct property_page *pp,
613 struct extviewer *ev);
614static void property_page_show_extviewer(struct property_page *pp,
615 struct extviewer *ev);
616static void property_page_store_creation_tag(struct property_page *pp,
617 int tag, int count);
618static void property_page_remove_creation_tag(struct property_page *pp,
619 int tag);
620static bool property_page_tag_is_known(struct property_page *pp, int tag);
621static void property_page_clear_tags(struct property_page *pp);
622static void property_page_apply_button_clicked(GtkButton *button,
623 gpointer userdata);
624static void property_page_refresh_button_clicked(GtkButton *button,
625 gpointer userdata);
626static void property_page_create_button_clicked(GtkButton *button,
627 gpointer userdata);
628static void property_page_destroy_button_clicked(GtkButton *button,
629 gpointer userdata);
630
631
632#define property_page_objprop_iterate(ARG_pp, NAME_op) \
633 TYPED_HASH_DATA_ITERATE(struct objprop *, (ARG_pp)->objprop_table, NAME_op)
634#define property_page_objprop_iterate_end HASH_DATA_ITERATE_END
635
636#define property_page_objbind_iterate(ARG_pp, NAME_ob) \
637 TYPED_HASH_DATA_ITERATE(struct objbind *, (ARG_pp)->objbind_table, NAME_ob)
638#define property_page_objbind_iterate_end HASH_DATA_ITERATE_END
639
640
641/****************************************************************************
642 Property editor declarations.
643****************************************************************************/
644 struct property_editor {
645 GtkWidget *widget;
646 GtkWidget *notebook;
647
648 struct property_page *property_pages[NUM_OBJTYPES];
649};
650
651static struct property_editor *property_editor_new(void);
652static bool property_editor_add_page(struct property_editor *pe,
653 enum editor_object_type objtype);
654static struct property_page *
655 property_editor_get_page(struct property_editor *pe,
656 enum editor_object_type objtype);
657
658 static struct property_editor *the_property_editor;
659
660
661/************************************************************************/
664 static const char *objtype_get_name(enum editor_object_type objtype)
665{
666 switch (objtype) {
667 case OBJTYPE_TILE:
668 return _("Tile");
669 case OBJTYPE_STARTPOS:
670 return _("Start Position");
671 case OBJTYPE_UNIT:
672 return _("Unit");
673 case OBJTYPE_CITY:
674 return _("City");
675 case OBJTYPE_PLAYER:
676 return _("Player");
677 case OBJTYPE_GAME:
678 return Q_("?play:Game");
679 case NUM_OBJTYPES:
680 break;
681 }
682
683 log_error("%s() Unhandled request to get name of object type %d.",
684 __FUNCTION__, objtype);
685 return "Unknown";
686}
687
688/************************************************************************/
693 static int objtype_get_id_from_object(enum editor_object_type objtype,
694 gpointer object)
695{
696 switch (objtype) {
697 case OBJTYPE_TILE:
698 return tile_index((struct tile *) object);
699 case OBJTYPE_STARTPOS:
700 return startpos_number((struct startpos *) object);
701 case OBJTYPE_UNIT:
702 return ((struct unit *) object)->id;
703 case OBJTYPE_CITY:
704 return ((struct city *) object)->id;
705 case OBJTYPE_PLAYER:
706 return player_number((struct player *) object);
707 case OBJTYPE_GAME:
708 return 1;
709 case NUM_OBJTYPES:
710 break;
711 }
712
713 log_error("%s(): Unhandled request to get object ID from object %p of "
714 "type %d (%s).", __FUNCTION__, object, objtype,
715 objtype_get_name(objtype));
716 return -1;
717}
718
719/************************************************************************/
722 static gpointer objtype_get_object_from_id(enum editor_object_type objtype,
723 int id)
724{
725 switch (objtype) {
726 case OBJTYPE_TILE:
727 return index_to_tile(&(wld.map), id);
728 case OBJTYPE_STARTPOS:
729 return map_startpos_by_number(id);
730 case OBJTYPE_UNIT:
731 return game_unit_by_number(id);
732 case OBJTYPE_CITY:
733 return game_city_by_number(id);
734 case OBJTYPE_PLAYER:
735 return player_by_number(id);
736 case OBJTYPE_GAME:
737 return &game;
738 case NUM_OBJTYPES:
739 break;
740 }
741
742 log_error("%s(): Unhandled request to get object of type %d (%s) "
743 "with ID %d.", __FUNCTION__, objtype,
744 objtype_get_name(objtype), id);
745 return NULL;
746}
747
748/************************************************************************/
753 static bool objtype_is_conserved(enum editor_object_type objtype)
754{
755 switch (objtype) {
756 case OBJTYPE_TILE:
757 case OBJTYPE_GAME:
758 return TRUE;
759 case OBJTYPE_STARTPOS:
760 case OBJTYPE_UNIT:
761 case OBJTYPE_CITY:
762 case OBJTYPE_PLAYER:
763 return FALSE;
764 case NUM_OBJTYPES:
765 break;
766 }
767
768 log_error("%s(): Unhandled request for object type %d (%s)).",
769 __FUNCTION__, objtype, objtype_get_name(objtype));
770 return TRUE;
771}
772
773/************************************************************************/
776 static const char *valtype_get_name(enum value_types valtype)
777{
778 switch (valtype) {
779 case VALTYPE_NONE:
780 return "none";
781 case VALTYPE_STRING:
782 return "string";
783 case VALTYPE_INT:
784 return "int";
785 case VALTYPE_BOOL:
786 return "bool";
787 case VALTYPE_PIXBUF:
788 return "pixbuf";
789 case VALTYPE_BUILT_ARRAY:
790 return "struct built_status[B_LAST]";
791 case VALTYPE_INVENTIONS_ARRAY:
792 return "bool[A_LAST]";
793 case VALTYPE_BV_SPECIAL:
794 return "bv_special";
795 case VALTYPE_BV_ROADS:
796 return "bv_roads";
797 case VALTYPE_BV_BASES:
798 return "bv_bases";
799 case VALTYPE_NATION:
800 return "nation";
801 case VALTYPE_NATION_HASH:
802 return "struct nation_hash";
803 case VALTYPE_GOV:
804 return "government";
805 case VALTYPE_TILE_VISION_DATA:
806 return "struct tile_vision_data";
807 }
808
809 log_error("%s(): unhandled value type %d.", __FUNCTION__, valtype);
810 return "void";
811}
812
813/************************************************************************/
817 static void add_column(GtkWidget *view,
818 int col_id,
819 const char *name,
820 GType gtype,
821 bool editable,
822 bool is_radio,
823 GCallback edit_callback,
824 gpointer userdata)
825{
826 GtkCellRenderer *cell;
827 GtkTreeViewColumn *col;
828 const char *attr = NULL;
829
830 if (gtype == G_TYPE_BOOLEAN) {
831 cell = gtk_cell_renderer_toggle_new();
832 gtk_cell_renderer_toggle_set_radio(GTK_CELL_RENDERER_TOGGLE(cell),
833 is_radio);
834 if (editable) {
835 g_signal_connect(cell, "toggled", edit_callback, userdata);
836 }
837 attr = "active";
838 } else if (gtype == GDK_TYPE_PIXBUF) {
839 cell = gtk_cell_renderer_pixbuf_new();
840 attr = "pixbuf";
841 } else {
842 cell = gtk_cell_renderer_text_new();
843 if (editable) {
844 g_object_set(cell, "editable", TRUE, NULL);
845 g_signal_connect(cell, "edited", edit_callback, userdata);
846 }
847 attr = "text";
848 }
849
850 col = gtk_tree_view_column_new_with_attributes(name, cell,
851 attr, col_id, NULL);
852 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
853}
854
855/************************************************************************/
859 static gchar *propval_as_string(struct propval *pv)
860{
861 int count = 0;
862
863 fc_assert_ret_val(NULL != pv, 0);
864
865 switch (pv->valtype) {
866 case VALTYPE_NONE:
867 return g_strdup("");
868
869 case VALTYPE_INT:
870 return g_strdup_printf("%d", pv->data.v_int);
871
872 case VALTYPE_BOOL:
873 return g_strdup_printf("%s", pv->data.v_bool ? _("TRUE") : _("FALSE"));
874
875 case VALTYPE_NATION:
876 return g_strdup_printf("%s", nation_adjective_translation(pv->data.v_nation));
877
878 case VALTYPE_GOV:
879 return g_strdup_printf("%s", government_name_translation(pv->data.v_gov));
880
881 case VALTYPE_BUILT_ARRAY:
882 {
883 int great_wonder_count = 0, small_wonder_count = 0, building_count = 0;
884 int id;
885
886 improvement_iterate(pimprove) {
887 id = improvement_index(pimprove);
888 if (pv->data.v_built[id].turn < 0) {
889 continue;
890 }
891 if (is_great_wonder(pimprove)) {
892 great_wonder_count++;
893 } else if (is_small_wonder(pimprove)) {
894 small_wonder_count++;
895 } else {
896 building_count++;
897 }
898 } improvement_iterate_end;
899 /* TRANS: "Number of buildings, number of small
900 * wonders (e.g. palace), number of great wonders." */
901 return g_strdup_printf(_("%db %ds %dW"),
902 building_count, small_wonder_count,
903 great_wonder_count);
904 }
905
906 case VALTYPE_INVENTIONS_ARRAY:
907 advance_index_iterate(A_FIRST, tech) {
908 if (BV_ISSET(pv->data.v_bv_inventions, tech)) {
909 count++;
910 }
911 } advance_index_iterate_end;
912 /* TRANS: "Number of technologies known". */
913 return g_strdup_printf(_("%d known"), count);
914
915 case VALTYPE_BV_SPECIAL:
916 extra_type_by_cause_iterate(EC_SPECIAL, spe) {
917 if (BV_ISSET(pv->data.v_bv_special, spe->data.special_idx)) {
918 count++;
919 }
920 } extra_type_by_cause_iterate_end;
921 /* TRANS: "The number of terrain specials (e.g. hut,
922 * river, pollution, etc.) present on a tile." */
923 return g_strdup_printf(_("%d present"), count);
924
925 case VALTYPE_BV_ROADS:
926 extra_type_by_cause_iterate(EC_ROAD, pextra) {
927 struct road_type *proad = extra_road_get(pextra);
928
929 if (BV_ISSET(pv->data.v_bv_roads, road_number(proad))) {
930 count++;
931 }
932 } extra_type_by_cause_iterate_end;
933 return g_strdup_printf(_("%d present"), count);
934
935 case VALTYPE_BV_BASES:
936 extra_type_by_cause_iterate(EC_BASE, pextra) {
937 struct base_type *pbase = extra_base_get(pextra);
938
939 if (BV_ISSET(pv->data.v_bv_bases, base_number(pbase))) {
940 count++;
941 }
942 } extra_type_by_cause_iterate_end;
943 return g_strdup_printf(_("%d present"), count);
944
945 case VALTYPE_NATION_HASH:
946 count = nation_hash_size(pv->data.v_nation_hash);
947 if (0 == count) {
948 return g_strdup(_("All nations"));
949 } else {
950 return g_strdup_printf(PL_("%d nation", "%d nations",
951 count), count);
952 }
953
954 case VALTYPE_STRING:
955 /* Assume it is a very long string. */
956 count = strlen(pv->data.v_const_string);
957 return g_strdup_printf(PL_("%d byte", "%d bytes", count),
958 count);
959
960 case VALTYPE_PIXBUF:
961 case VALTYPE_TILE_VISION_DATA:
962 break;
963 }
964
965 log_error("%s(): Unhandled value type %d for property value %p.",
966 __FUNCTION__, pv->valtype, pv);
967 return g_strdup("");
968}
969
970/************************************************************************/
974 static gchar *built_status_to_string(struct built_status *bs)
975{
976 int turn_built;
977
978 turn_built = bs->turn;
979
980 if (turn_built == I_NEVER) {
981 /* TRANS: Improvement never built. */
982 return g_strdup(_("(never)"));
983 } else if (turn_built == I_DESTROYED) {
984 /* TRANS: Improvement was destroyed. */
985 return g_strdup(_("(destroyed)"));
986 } else {
987 return g_strdup_printf("%d", turn_built);
988 }
989}
990
991/************************************************************************/
995 static bool can_create_unit_at_tile(struct tile *ptile)
996{
997 struct unit *vunit;
998 struct city *pcity;
999 struct player *pplayer;
1000 bool ret;
1001
1002 if (!ptile) {
1003 return FALSE;
1004 }
1005
1006 vunit = editor_unit_virtual_create();
1007 if (!vunit) {
1008 return FALSE;
1009 }
1010
1011 pcity = tile_city(ptile);
1012 pplayer = unit_owner(vunit);
1013
1014 ret = (can_unit_exist_at_tile(&(wld.map), vunit, ptile)
1015 && !is_non_allied_unit_tile(ptile, pplayer)
1016 && (pcity == NULL
1017 || pplayers_allied(city_owner(pcity),
1018 unit_owner(vunit))));
1019 free(vunit);
1020
1021 return ret;
1022}
1023
1024/************************************************************************/
1027 static int get_next_unique_tag(void)
1028{
1029 static int tag_series = 0;
1030
1031 tag_series++;
1032 return tag_series;
1033}
1034
1035/************************************************************************/
1038 static struct propval *propval_copy(struct propval *pv)
1039{
1040 struct propval *pv_copy;
1041 size_t size;
1042
1043 if (!pv) {
1044 return NULL;
1045 }
1046
1047 pv_copy = fc_calloc(1, sizeof(*pv));
1048 pv_copy->valtype = pv->valtype;
1049
1050 switch (pv->valtype) {
1051 case VALTYPE_NONE:
1052 return pv_copy;
1053 case VALTYPE_INT:
1054 pv_copy->data.v_int = pv->data.v_int;
1055 return pv_copy;
1056 case VALTYPE_BOOL:
1057 pv_copy->data.v_bool = pv->data.v_bool;
1058 return pv_copy;
1059 case VALTYPE_STRING:
1060 pv_copy->data.v_string = fc_strdup(pv->data.v_string);
1061 pv_copy->must_free = TRUE;
1062 return pv_copy;
1063 case VALTYPE_PIXBUF:
1064 g_object_ref(pv->data.v_pixbuf);
1065 pv_copy->data.v_pixbuf = pv->data.v_pixbuf;
1066 pv_copy->must_free = TRUE;
1067 return pv_copy;
1068 case VALTYPE_BUILT_ARRAY:
1069 size = B_LAST * sizeof(struct built_status);
1070 pv_copy->data.v_pointer = fc_malloc(size);
1071 memcpy(pv_copy->data.v_pointer, pv->data.v_pointer, size);
1072 pv_copy->must_free = TRUE;
1073 return pv_copy;
1074 case VALTYPE_BV_SPECIAL:
1075 pv_copy->data.v_bv_special = pv->data.v_bv_special;
1076 return pv_copy;
1077 case VALTYPE_BV_ROADS:
1078 pv_copy->data.v_bv_roads = pv->data.v_bv_roads;
1079 return pv_copy;
1080 case VALTYPE_BV_BASES:
1081 pv_copy->data.v_bv_bases = pv->data.v_bv_bases;
1082 return pv_copy;
1083 case VALTYPE_NATION:
1084 pv_copy->data.v_nation = pv->data.v_nation;
1085 return pv_copy;
1086 case VALTYPE_GOV:
1087 pv_copy->data.v_gov = pv->data.v_gov;
1088 return pv_copy;
1089 case VALTYPE_NATION_HASH:
1090 pv_copy->data.v_nation_hash
1091 = nation_hash_copy(pv->data.v_nation_hash);
1092 pv_copy->must_free = TRUE;
1093 return pv_copy;
1094 case VALTYPE_INVENTIONS_ARRAY:
1095 pv_copy->data.v_bv_inventions = pv->data.v_bv_inventions;
1096 return pv_copy;
1097 case VALTYPE_TILE_VISION_DATA:
1098 size = sizeof(struct tile_vision_data);
1099 pv_copy->data.v_tile_vision = fc_malloc(size);
1100 pv_copy->data.v_tile_vision->tile_known
1101 = pv->data.v_tile_vision->tile_known;
1102 vision_layer_iterate(v) {
1103 pv_copy->data.v_tile_vision->tile_seen[v]
1104 = pv->data.v_tile_vision->tile_seen[v];
1105 } vision_layer_iterate_end;
1106 pv_copy->must_free = TRUE;
1107 return pv_copy;
1108 }
1109
1110 log_error("%s(): Unhandled value type %d for property value %p.",
1111 __FUNCTION__, pv->valtype, pv);
1112 pv_copy->data = pv->data;
1113 return pv_copy;
1114}
1115
1116/************************************************************************/
1120 static void propval_free(struct propval *pv)
1121{
1122 if (!pv) {
1123 return;
1124 }
1125
1126 propval_free_data(pv);
1127 free(pv);
1128}
1129
1130/************************************************************************/
1134 static void propval_free_data(struct propval *pv)
1135{
1136 if (!pv || !pv->must_free) {
1137 return;
1138 }
1139
1140 switch (pv->valtype) {
1141 case VALTYPE_NONE:
1142 case VALTYPE_INT:
1143 case VALTYPE_BOOL:
1144 case VALTYPE_BV_SPECIAL:
1145 case VALTYPE_BV_ROADS:
1146 case VALTYPE_BV_BASES:
1147 case VALTYPE_NATION:
1148 case VALTYPE_GOV:
1149 return;
1150 case VALTYPE_PIXBUF:
1151 g_object_unref(pv->data.v_pixbuf);
1152 return;
1153 case VALTYPE_STRING:
1154 case VALTYPE_BUILT_ARRAY:
1155 case VALTYPE_INVENTIONS_ARRAY:
1156 case VALTYPE_TILE_VISION_DATA:
1157 free(pv->data.v_pointer);
1158 return;
1159 case VALTYPE_NATION_HASH:
1160 nation_hash_destroy(pv->data.v_nation_hash);
1161 return;
1162 }
1163
1164 log_error("%s(): Unhandled request to free data %p (type %s).",
1165 __FUNCTION__, pv->data.v_pointer, valtype_get_name(pv->valtype));
1166}
1167
1168/************************************************************************/
1171 static bool propval_equal(struct propval *pva,
1172 struct propval *pvb)
1173{
1174 if (!pva || !pvb) {
1175 return pva == pvb;
1176 }
1177
1178 if (pva->valtype != pvb->valtype) {
1179 return FALSE;
1180 }
1181
1182 switch (pva->valtype) {
1183 case VALTYPE_NONE:
1184 return TRUE;
1185 case VALTYPE_INT:
1186 return pva->data.v_int == pvb->data.v_int;
1187 case VALTYPE_BOOL:
1188 return pva->data.v_bool == pvb->data.v_bool;
1189 case VALTYPE_STRING:
1190 if (pva->data.v_const_string != NULL
1191 && pvb->data.v_const_string != NULL) {
1192 return !strcmp(pva->data.v_const_string,
1193 pvb->data.v_const_string);
1194 }
1195 return pva->data.v_const_string == pvb->data.v_const_string;
1196 case VALTYPE_PIXBUF:
1197 return pva->data.v_pixbuf == pvb->data.v_pixbuf;
1198 case VALTYPE_BUILT_ARRAY:
1199 if (pva->data.v_pointer == pvb->data.v_pointer) {
1200 return TRUE;
1201 } else if (!pva->data.v_pointer || !pvb->data.v_pointer) {
1202 return FALSE;
1203 }
1204
1205 improvement_iterate(pimprove) {
1206 int id, vatb, vbtb;
1207 id = improvement_index(pimprove);
1208 vatb = pva->data.v_built[id].turn;
1209 vbtb = pvb->data.v_built[id].turn;
1210 if (vatb < 0 && vbtb < 0) {
1211 continue;
1212 }
1213 if (vatb != vbtb) {
1214 return FALSE;
1215 }
1216 } improvement_iterate_end;
1217 return TRUE;
1218 case VALTYPE_INVENTIONS_ARRAY:
1219 return BV_ARE_EQUAL(pva->data.v_bv_inventions, pvb->data.v_bv_inventions);
1220 case VALTYPE_BV_SPECIAL:
1221 return BV_ARE_EQUAL(pva->data.v_bv_special, pvb->data.v_bv_special);
1222 case VALTYPE_BV_ROADS:
1223 return BV_ARE_EQUAL(pva->data.v_bv_roads, pvb->data.v_bv_roads);
1224 case VALTYPE_BV_BASES:
1225 return BV_ARE_EQUAL(pva->data.v_bv_bases, pvb->data.v_bv_bases);
1226 case VALTYPE_NATION:
1227 return pva->data.v_nation == pvb->data.v_nation;
1228 case VALTYPE_NATION_HASH:
1229 return nation_hashes_are_equal(pva->data.v_nation_hash,
1230 pvb->data.v_nation_hash);
1231 case VALTYPE_GOV:
1232 return pva->data.v_gov == pvb->data.v_gov;
1233 case VALTYPE_TILE_VISION_DATA:
1234 if (!BV_ARE_EQUAL(pva->data.v_tile_vision->tile_known,
1235 pvb->data.v_tile_vision->tile_known)) {
1236 return FALSE;
1237 }
1238 vision_layer_iterate(v) {
1239 if (!BV_ARE_EQUAL(pva->data.v_tile_vision->tile_seen[v],
1240 pvb->data.v_tile_vision->tile_seen[v])) {
1241 return FALSE;
1242 }
1243 } vision_layer_iterate_end;
1244 return TRUE;
1245 }
1246
1247 log_error("%s(): Unhandled value type %d for property values %p and %p.",
1248 __FUNCTION__, pva->valtype, pva, pvb);
1249 return pva->data.v_pointer == pvb->data.v_pointer;
1250}
1251
1252/************************************************************************/
1258 static struct propstate *propstate_new(struct objprop *op,
1259 struct propval *pv)
1260{
1261 struct propstate *ps;
1262
1263 if (!op) {
1264 return NULL;
1265 }
1266
1267 ps = fc_calloc(1, sizeof(*ps));
1268 ps->property_id = objprop_get_id(op);
1269 ps->property_value = pv;
1270
1271 return ps;
1272}
1273
1274/************************************************************************/
1277 static void propstate_clear_value(struct propstate *ps)
1278{
1279 if (!ps) {
1280 return;
1281 }
1282
1283 propval_free(ps->property_value);
1284 ps->property_value = NULL;
1285}
1286
1287/************************************************************************/
1290 static void propstate_destroy(struct propstate *ps)
1291{
1292 if (!ps) {
1293 return;
1294 }
1295 propstate_clear_value(ps);
1296 free(ps);
1297}
1298
1299/************************************************************************/
1305 static void propstate_set_value(struct propstate *ps,
1306 struct propval *pv)
1307{
1308 if (!ps) {
1309 return;
1310 }
1311 propstate_clear_value(ps);
1312 ps->property_value = pv;
1313}
1314
1315/************************************************************************/
1320 static struct propval *propstate_get_value(struct propstate *ps)
1321{
1322 if (!ps) {
1323 return NULL;
1324 }
1325 return ps->property_value;
1326}
1327
1328/************************************************************************/
1332 static struct objbind *objbind_new(enum editor_object_type objtype,
1333 gpointer object)
1334{
1335 struct objbind *ob;
1336 int id;
1337
1338 if (object == NULL) {
1339 return NULL;
1340 }
1341
1342 id = objtype_get_id_from_object(objtype, object);
1343 if (id < 0) {
1344 return NULL;
1345 }
1346
1347 ob = fc_calloc(1, sizeof(*ob));
1348 ob->object_id = id;
1349 ob->objtype = objtype;
1350 ob->propstate_table = propstate_hash_new();
1351
1352 return ob;
1353}
1354
1355/************************************************************************/
1358 static gpointer objbind_get_object(struct objbind *ob)
1359{
1360 int id;
1361
1362 if (!ob) {
1363 return NULL;
1364 }
1365
1366 id = objbind_get_object_id(ob);
1367
1368 return objtype_get_object_from_id(ob->objtype, id);
1369}
1370
1371/************************************************************************/
1374 static int objbind_get_object_id(struct objbind *ob)
1375{
1376 if (NULL == ob) {
1377 return -1;
1378 }
1379 return ob->object_id;
1380}
1381
1382/************************************************************************/
1387 static void objbind_request_destroy_object(struct objbind *ob)
1388{
1389 struct connection *my_conn = &client.conn;
1390 enum editor_object_type objtype;
1391 int id;
1392
1393 if (!ob) {
1394 return;
1395 }
1396
1397 objtype = objbind_get_objtype(ob);
1398 if (objtype_is_conserved(objtype)) {
1399 return;
1400 }
1401
1402 id = objbind_get_object_id(ob);
1403
1404 switch (objtype) {
1405 case OBJTYPE_STARTPOS:
1406 dsend_packet_edit_startpos(my_conn, id, TRUE, 0);
1407 return;
1408 case OBJTYPE_UNIT:
1409 dsend_packet_edit_unit_remove_by_id(my_conn, id, id);
1410 return;
1411 case OBJTYPE_CITY:
1412 dsend_packet_edit_city_remove(my_conn, id, id);
1413 return;
1414 case OBJTYPE_PLAYER:
1415 dsend_packet_edit_player_remove(my_conn, id);
1416 return;
1417 case OBJTYPE_TILE:
1418 case OBJTYPE_GAME:
1419 case NUM_OBJTYPES:
1420 break;
1421 }
1422
1423 log_error("%s(): Unhandled request to destroy object %p (ID %d) of type "
1424 "%d (%s).", __FUNCTION__, objbind_get_object(ob), id, objtype,
1425 objtype_get_name(objtype));
1426}
1427
1428/************************************************************************/
1435 static struct propval *objbind_get_value_from_object(struct objbind *ob,
1436 struct objprop *op)
1437{
1438 enum editor_object_type objtype;
1439 enum object_property_ids propid;
1440 struct propval *pv;
1441
1442 if (!ob || !op) {
1443 return NULL;
1444 }
1445
1446 objtype = objbind_get_objtype(ob);
1447 propid = objprop_get_id(op);
1448
1449 pv = fc_calloc(1, sizeof(*pv));
1450 pv->valtype = objprop_get_valtype(op);
1451
1452 switch (objtype) {
1453 case OBJTYPE_TILE:
1454 {
1455 const struct tile *ptile = objbind_get_object(ob);
1456 int tile_x, tile_y, nat_x, nat_y;
1457
1458 if (NULL == ptile) {
1459 goto FAILED;
1460 }
1461
1462 index_to_map_pos(&tile_x, &tile_y, tile_index(ptile));
1463 index_to_native_pos(&nat_x, &nat_y, tile_index(ptile));
1464
1465 switch (propid) {
1466 case OPID_TILE_IMAGE:
1467 pv->data.v_pixbuf = create_tile_pixbuf(ptile);
1468 pv->must_free = TRUE;
1469 break;
1470#ifdef FREECIV_DEBUG
1471 case OPID_TILE_ADDRESS:
1472 pv->data.v_string = g_strdup_printf("%p", ptile);
1473 pv->must_free = TRUE;
1474 break;
1475#endif /* FREECIV_DEBUG */
1476 case OPID_TILE_TERRAIN:
1477 {
1478 const struct terrain *pterrain = tile_terrain(ptile);
1479
1480 if (NULL != pterrain) {
1481 pv->data.v_const_string = terrain_name_translation(pterrain);
1482 } else {
1483 pv->data.v_const_string = "";
1484 }
1485 }
1486 break;
1487 case OPID_TILE_RESOURCE:
1488 {
1489 const struct extra_type *presource = tile_resource(ptile);
1490
1491 if (NULL != presource) {
1492 pv->data.v_const_string = extra_name_translation(presource);
1493 } else {
1494 pv->data.v_const_string = "";
1495 }
1496 }
1497 break;
1498 case OPID_TILE_XY:
1499 pv->data.v_string = g_strdup_printf("(%d, %d)", tile_x, tile_y);
1500 pv->must_free = TRUE;
1501 break;
1502 case OPID_TILE_INDEX:
1503 pv->data.v_int = tile_index(ptile);
1504 break;
1505 case OPID_TILE_X:
1506 pv->data.v_int = tile_x;
1507 break;
1508 case OPID_TILE_Y:
1509 pv->data.v_int = tile_y;
1510 break;
1511 case OPID_TILE_NAT_X:
1512 pv->data.v_int = nat_x;
1513 break;
1514 case OPID_TILE_NAT_Y:
1515 pv->data.v_int = nat_y;
1516 break;
1517 case OPID_TILE_CONTINENT:
1518 pv->data.v_int = ptile->continent;
1519 break;
1520 case OPID_TILE_SPECIALS:
1521 BV_CLR_ALL(pv->data.v_bv_special);
1522 extra_type_by_cause_iterate(EC_SPECIAL, pextra) {
1523 if (tile_has_extra(ptile, pextra)) {
1524 BV_SET(pv->data.v_bv_special, pextra->data.special_idx);
1525 }
1526 } extra_type_by_cause_iterate_end;
1527 break;
1528 case OPID_TILE_ROADS:
1529 BV_CLR_ALL(pv->data.v_bv_roads);
1530 extra_type_by_cause_iterate(EC_ROAD, pextra) {
1531 if (tile_has_extra(ptile, pextra)) {
1532 BV_SET(pv->data.v_bv_roads, road_number(extra_road_get(pextra)));
1533 }
1534 } extra_type_by_cause_iterate_end;
1535 break;
1536 case OPID_TILE_BASES:
1537 BV_CLR_ALL(pv->data.v_bv_bases);
1538 extra_type_by_cause_iterate(EC_BASE, pextra) {
1539 if (tile_has_extra(ptile, pextra)) {
1540 BV_SET(pv->data.v_bv_bases, base_number(extra_base_get(pextra)));
1541 }
1542 } extra_type_by_cause_iterate_end;
1543 break;
1544 case OPID_TILE_VISION:
1545 pv->data.v_tile_vision = fc_malloc(sizeof(struct tile_vision_data));
1546
1547 /* The server saves the known tiles and the player vision in special
1548 * bitvectors with the number of tiles as index. Here we want the
1549 * information for one tile. Thus, the data is transformed to
1550 * bitvectors with the number of player slots as index. */
1551 BV_CLR_ALL(pv->data.v_tile_vision->tile_known);
1552 players_iterate(pplayer) {
1553 if (dbv_isset(&pplayer->tile_known, tile_index(ptile))) {
1554 BV_SET(pv->data.v_tile_vision->tile_known,
1555 player_index(pplayer));
1556 }
1557 } players_iterate_end;
1558
1559 vision_layer_iterate(v) {
1560 BV_CLR_ALL(pv->data.v_tile_vision->tile_seen[v]);
1561 players_iterate(pplayer) {
1562 if (fc_funcs->player_tile_vision_get(ptile, pplayer, v)) {
1563 BV_SET(pv->data.v_tile_vision->tile_seen[v],
1564 player_index(pplayer));
1565 }
1566 } players_iterate_end;
1567 } vision_layer_iterate_end;
1568 pv->must_free = TRUE;
1569 break;
1570 case OPID_TILE_LABEL:
1571 if (ptile->label != NULL) {
1572 pv->data.v_const_string = ptile->label;
1573 } else {
1574 pv->data.v_const_string = "";
1575 }
1576 break;
1577 default:
1578 log_error("%s(): Unhandled request for value of property %d "
1579 "(%s) from object of type \"%s\".", __FUNCTION__,
1580 propid, objprop_get_name(op), objtype_get_name(objtype));
1581 goto FAILED;
1582 }
1583 }
1584 return pv;
1585
1586 case OBJTYPE_STARTPOS:
1587 {
1588 const struct startpos *psp = objbind_get_object(ob);
1589 const struct tile *ptile;
1590
1591 if (NULL == psp) {
1592 goto FAILED;
1593 }
1594
1595 switch (propid) {
1596 case OPID_STARTPOS_IMAGE:
1597 ptile = startpos_tile(psp);
1598 pv->data.v_pixbuf = create_tile_pixbuf(ptile);
1599 pv->must_free = TRUE;
1600 break;
1601 case OPID_STARTPOS_XY:
1602 ptile = startpos_tile(psp);
1603 pv->data.v_string = g_strdup_printf("(%d, %d)", TILE_XY(ptile));
1604 pv->must_free = TRUE;
1605 break;
1606 case OPID_STARTPOS_EXCLUDE:
1607 pv->data.v_bool = startpos_is_excluding(psp);
1608 break;
1609 case OPID_STARTPOS_NATIONS:
1610 pv->data.v_nation_hash = nation_hash_copy(startpos_raw_nations(psp));
1611 pv->must_free = TRUE;
1612 break;
1613 default:
1614 log_error("%s(): Unhandled request for value of property %d "
1615 "(%s) from object of type \"%s\".", __FUNCTION__,
1616 propid, objprop_get_name(op), objtype_get_name(objtype));
1617 goto FAILED;
1618 }
1619 }
1620 return pv;
1621
1622 case OBJTYPE_UNIT:
1623 {
1624 struct unit *punit = objbind_get_object(ob);
1625
1626 if (NULL == punit) {
1627 goto FAILED;
1628 }
1629
1630 switch (propid) {
1631 case OPID_UNIT_IMAGE:
1632 pv->data.v_pixbuf = create_unit_pixbuf(punit);
1633 pv->must_free = TRUE;
1634 break;
1635#ifdef FREECIV_DEBUG
1636 case OPID_UNIT_ADDRESS:
1637 pv->data.v_string = g_strdup_printf("%p", punit);
1638 pv->must_free = TRUE;
1639 break;
1640#endif /* FREECIV_DEBUG */
1641 case OPID_UNIT_XY:
1642 {
1643 const struct tile *ptile = unit_tile(punit);
1644
1645 pv->data.v_string = g_strdup_printf("(%d, %d)", TILE_XY(ptile));
1646 pv->must_free = TRUE;
1647 }
1648 break;
1649 case OPID_UNIT_ID:
1650 pv->data.v_int = punit->id;
1651 break;
1652 case OPID_UNIT_TYPE:
1653 {
1654 const struct unit_type *putype = unit_type_get(punit);
1655
1656 pv->data.v_const_string = utype_name_translation(putype);
1657 }
1658 break;
1659 case OPID_UNIT_MOVES_LEFT:
1660 pv->data.v_int = punit->moves_left;
1661 break;
1662 case OPID_UNIT_FUEL:
1663 pv->data.v_int = punit->fuel;
1664 break;
1665 case OPID_UNIT_MOVED:
1666 pv->data.v_bool = punit->moved;
1667 break;
1668 case OPID_UNIT_DONE_MOVING:
1669 pv->data.v_bool = punit->done_moving;
1670 break;
1671 case OPID_UNIT_HP:
1672 pv->data.v_int = punit->hp;
1673 break;
1674 case OPID_UNIT_VETERAN:
1675 pv->data.v_int = punit->veteran;
1676 break;
1677 case OPID_UNIT_STAY:
1678 pv->data.v_bool = punit->stay;
1679 break;
1680 default:
1681 log_error("%s(): Unhandled request for value of property %d "
1682 "(%s) from object of type \"%s\".", __FUNCTION__,
1683 propid, objprop_get_name(op), objtype_get_name(objtype));
1684 goto FAILED;
1685 }
1686 }
1687 return pv;
1688
1689 case OBJTYPE_CITY:
1690 {
1691 const struct city *pcity = objbind_get_object(ob);
1692
1693 if (NULL == pcity) {
1694 goto FAILED;
1695 }
1696
1697 switch (propid) {
1698 case OPID_CITY_IMAGE:
1699 pv->data.v_pixbuf = create_city_pixbuf(pcity);
1700 pv->must_free = TRUE;
1701 break;
1702#ifdef FREECIV_DEBUG
1703 case OPID_CITY_ADDRESS:
1704 pv->data.v_string = g_strdup_printf("%p", pcity);
1705 pv->must_free = TRUE;
1706 break;
1707#endif /* FREECIV_DEBUG */
1708 case OPID_CITY_XY:
1709 {
1710 const struct tile *ptile = city_tile(pcity);
1711
1712 pv->data.v_string = g_strdup_printf("(%d, %d)", TILE_XY(ptile));
1713 pv->must_free = TRUE;
1714 }
1715 break;
1716 case OPID_CITY_ID:
1717 pv->data.v_int = pcity->id;
1718 break;
1719 case OPID_CITY_NAME:
1720 pv->data.v_const_string = pcity->name;
1721 break;
1722 case OPID_CITY_SIZE:
1723 pv->data.v_int = city_size_get(pcity);
1724 break;
1725 case OPID_CITY_HISTORY:
1726 pv->data.v_int = pcity->history;
1727 break;
1728 case OPID_CITY_BUILDINGS:
1729 pv->data.v_built = fc_malloc(sizeof(pcity->built));
1730 memcpy(pv->data.v_built, pcity->built, sizeof(pcity->built));
1731 pv->must_free = TRUE;
1732 break;
1733 case OPID_CITY_FOOD_STOCK:
1734 pv->data.v_int = pcity->food_stock;
1735 break;
1736 case OPID_CITY_SHIELD_STOCK:
1737 pv->data.v_int = pcity->shield_stock;
1738 break;
1739 default:
1740 log_error("%s(): Unhandled request for value of property %d "
1741 "(%s) from object of type \"%s\".", __FUNCTION__,
1742 propid, objprop_get_name(op), objtype_get_name(objtype));
1743 goto FAILED;
1744 }
1745 }
1746 return pv;
1747
1748 case OBJTYPE_PLAYER:
1749 {
1750 const struct player *pplayer = objbind_get_object(ob);
1751 const struct research *presearch;
1752
1753 if (NULL == pplayer) {
1754 goto FAILED;
1755 }
1756
1757 switch (propid) {
1758 case OPID_PLAYER_NAME:
1759 pv->data.v_const_string = pplayer->name;
1760 break;
1761 case OPID_PLAYER_NATION:
1762 pv->data.v_nation = nation_of_player(pplayer);
1763 break;
1764 case OPID_PLAYER_GOV:
1765 pv->data.v_gov = pplayer->government;
1766 break;
1767 case OPID_PLAYER_AGE:
1768 pv->data.v_int = pplayer->turns_alive;
1769 break;
1770#ifdef FREECIV_DEBUG
1771 case OPID_PLAYER_ADDRESS:
1772 pv->data.v_string = g_strdup_printf("%p", pplayer);
1773 pv->must_free = TRUE;
1774 break;
1775#endif /* FREECIV_DEBUG */
1776 case OPID_PLAYER_INVENTIONS:
1777 presearch = research_get(pplayer);
1778 BV_CLR_ALL(pv->data.v_bv_inventions);
1779 advance_index_iterate(A_FIRST, tech) {
1780 if (TECH_KNOWN == research_invention_state(presearch, tech)) {
1781 BV_SET(pv->data.v_bv_inventions, tech);
1782 }
1783 } advance_index_iterate_end;
1784 break;
1785 case OPID_PLAYER_SCENARIO_RESERVED:
1786 pv->data.v_bool = player_has_flag(pplayer, PLRF_SCENARIO_RESERVED);
1787 break;
1788 case OPID_PLAYER_SCIENCE:
1789 presearch = research_get(pplayer);
1790 pv->data.v_int = presearch->bulbs_researched;
1791 break;
1792 case OPID_PLAYER_GOLD:
1793 pv->data.v_int = pplayer->economic.gold;
1794 break;
1795 default:
1796 log_error("%s(): Unhandled request for value of property %d "
1797 "(%s) from object of type \"%s\".", __FUNCTION__,
1798 propid, objprop_get_name(op), objtype_get_name(objtype));
1799 goto FAILED;
1800 }
1801 }
1802 return pv;
1803
1804 case OBJTYPE_GAME:
1805 {
1806 const struct civ_game *pgame = objbind_get_object(ob);
1807
1808 if (NULL == pgame) {
1809 goto FAILED;
1810 }
1811
1812 switch (propid) {
1813 case OPID_GAME_SCENARIO:
1814 pv->data.v_bool = pgame->scenario.is_scenario;
1815 break;
1816 case OPID_GAME_SCENARIO_NAME:
1817 pv->data.v_const_string = pgame->scenario.name;
1818 break;
1819 case OPID_GAME_SCENARIO_AUTHORS:
1820 pv->data.v_const_string = pgame->scenario.authors;
1821 break;
1822 case OPID_GAME_SCENARIO_DESC:
1823 pv->data.v_const_string = pgame->scenario_desc.description;
1824 break;
1825 case OPID_GAME_SCENARIO_RANDSTATE:
1826 pv->data.v_bool = pgame->scenario.save_random;
1827 break;
1828 case OPID_GAME_SCENARIO_PLAYERS:
1829 pv->data.v_bool = pgame->scenario.players;
1830 break;
1831 case OPID_GAME_STARTPOS_NATIONS:
1832 pv->data.v_bool = pgame->scenario.startpos_nations;
1833 break;
1834 case OPID_GAME_PREVENT_CITIES:
1835 pv->data.v_bool = pgame->scenario.prevent_new_cities;
1836 break;
1837 case OPID_GAME_LAKE_FLOODING:
1838 pv->data.v_bool = pgame->scenario.lake_flooding;
1839 break;
1840 case OPID_GAME_RULESET_LOCKED:
1841 pv->data.v_bool = pgame->scenario.ruleset_locked;
1842 break;
1843 default:
1844 log_error("%s(): Unhandled request for value of property %d "
1845 "(%s) from object of type \"%s\".", __FUNCTION__,
1846 propid, objprop_get_name(op), objtype_get_name(objtype));
1847 goto FAILED;
1848 }
1849 }
1850 return pv;
1851
1852 case NUM_OBJTYPES:
1853 break;
1854 }
1855
1856 log_error("%s(): Unhandled request for object type \"%s\" (nb %d).",
1857 __FUNCTION__, objtype_get_name(objtype), objtype);
1858
1859FAILED:
1860 if (NULL != pv) {
1861 free(pv);
1862 }
1863 return NULL;
1864}
1865
1866/************************************************************************/
1870 static bool objbind_get_allowed_value_span(struct objbind *ob,
1871 struct objprop *op,
1872 double *pmin,
1873 double *pmax,
1874 double *pstep,
1875 double *pbig_step)
1876{
1877 enum editor_object_type objtype;
1878 enum object_property_ids propid;
1879 double dummy;
1880
1881 /* Fill the values with something. */
1882 if (NULL != pmin) {
1883 *pmin = 0;
1884 } else {
1885 pmin = &dummy;
1886 }
1887 if (NULL != pmax) {
1888 *pmax = 1;
1889 } else {
1890 pmax = &dummy;
1891 }
1892 if (NULL != pstep) {
1893 *pstep = 1;
1894 } else {
1895 pstep = &dummy;
1896 }
1897 if (NULL != pbig_step) {
1898 *pbig_step = 1;
1899 } else {
1900 pbig_step = &dummy;
1901 }
1902
1903 if (!ob || !op) {
1904 return FALSE;
1905 }
1906
1907 propid = objprop_get_id(op);
1908 objtype = objbind_get_objtype(ob);
1909
1910 switch (objtype) {
1911 case OBJTYPE_TILE:
1912 case OBJTYPE_STARTPOS:
1913 log_error("%s(): Unhandled request for value range of property %d (%s) "
1914 "from object of type \"%s\".", __FUNCTION__,
1915 propid, objprop_get_name(op), objtype_get_name(objtype));
1916 return FALSE;
1917
1918 case OBJTYPE_UNIT:
1919 {
1920 const struct unit *punit = objbind_get_object(ob);
1921 const struct unit_type *putype;
1922
1923 if (NULL == punit) {
1924 return FALSE;
1925 }
1926
1927 putype = unit_type_get(punit);
1928
1929 switch (propid) {
1930 case OPID_UNIT_MOVES_LEFT:
1931 *pmin = 0;
1932 *pmax = MAX_MOVE_FRAGS;
1933 *pstep = 1;
1934 *pbig_step = 5;
1935 return TRUE;
1936 case OPID_UNIT_FUEL:
1937 *pmin = 0;
1938 *pmax = utype_fuel(putype);
1939 *pstep = 1;
1940 *pbig_step = 5;
1941 return TRUE;
1942 case OPID_UNIT_HP:
1943 *pmin = 1;
1944 *pmax = putype->hp;
1945 *pstep = 1;
1946 *pbig_step = 10;
1947 return TRUE;
1948 case OPID_UNIT_VETERAN:
1949 *pmin = 0;
1950 *pmax = utype_veteran_levels(putype) - 1;
1951 *pstep = 1;
1952 *pbig_step = 3;
1953 return TRUE;
1954 default:
1955 break;
1956 }
1957 }
1958 log_error("%s(): Unhandled request for value range of property %d (%s) "
1959 "from object of type \"%s\".", __FUNCTION__,
1960 propid, objprop_get_name(op), objtype_get_name(objtype));
1961 return FALSE;
1962
1963 case OBJTYPE_CITY:
1964 {
1965 const struct city *pcity = objbind_get_object(ob);
1966
1967 if (NULL == pcity) {
1968 return FALSE;
1969 }
1970
1971 switch (propid) {
1972 case OPID_CITY_SIZE:
1973 *pmin = 1;
1974 *pmax = MAX_CITY_SIZE;
1975 *pstep = 1;
1976 *pbig_step = 5;
1977 return TRUE;
1978 case OPID_CITY_HISTORY:
1979 *pmin = 0;
1980 *pmax = USHRT_MAX;
1981 *pstep = 1;
1982 *pbig_step = 10;
1983 return TRUE;
1984 case OPID_CITY_FOOD_STOCK:
1985 *pmin = 0;
1986 *pmax = city_granary_size(city_size_get(pcity));
1987 *pstep = 1;
1988 *pbig_step = 5;
1989 return TRUE;
1990 case OPID_CITY_SHIELD_STOCK:
1991 *pmin = 0;
1992 *pmax = USHRT_MAX; /* Limited to uint16 by city info packet. */
1993 *pstep = 1;
1994 *pbig_step = 10;
1995 return TRUE;
1996 default:
1997 break;
1998 }
1999 }
2000 log_error("%s(): Unhandled request for value range of property %d (%s) "
2001 "from object of type \"%s\".", __FUNCTION__,
2002 propid, objprop_get_name(op), objtype_get_name(objtype));
2003 return FALSE;
2004
2005 case OBJTYPE_PLAYER:
2006 switch (propid) {
2007 case OPID_PLAYER_SCIENCE:
2008 *pmin = 0;
2009 *pmax = 1000000; /* Arbitrary. */
2010 *pstep = 1;
2011 *pbig_step = 100;
2012 return TRUE;
2013 case OPID_PLAYER_GOLD:
2014 *pmin = 0;
2015 *pmax = 1000000; /* Arbitrary. */
2016 *pstep = 1;
2017 *pbig_step = 100;
2018 return TRUE;
2019 default:
2020 break;
2021 }
2022 log_error("%s(): Unhandled request for value range of property %d (%s) "
2023 "from object of type \"%s\".", __FUNCTION__,
2024 propid, objprop_get_name(op), objtype_get_name(objtype));
2025 return FALSE;
2026
2027 case OBJTYPE_GAME:
2028 log_error("%s(): Unhandled request for value range of property %d (%s) "
2029 "from object of type \"%s\".", __FUNCTION__,
2030 propid, objprop_get_name(op), objtype_get_name(objtype));
2031 return FALSE;
2032
2033 case NUM_OBJTYPES:
2034 break;
2035 }
2036
2037 log_error("%s(): Unhandled request for object type \"%s\" (nb %d).",
2038 __FUNCTION__, objtype_get_name(objtype), objtype);
2039 return FALSE;
2040}
2041
2042/************************************************************************/
2045 static void objbind_clear_modified_value(struct objbind *ob,
2046 struct objprop *op)
2047{
2048 if (!ob || !op || !ob->propstate_table) {
2049 return;
2050 }
2051
2052 propstate_hash_remove(ob->propstate_table, objprop_get_id(op));
2053}
2054
2055/************************************************************************/
2059 static bool objbind_property_is_modified(struct objbind *ob,
2060 struct objprop *op)
2061{
2062 if (!ob || !op) {
2063 return FALSE;
2064 }
2065
2066 if (objprop_is_readonly(op)) {
2067 return FALSE;
2068 }
2069
2070 return propstate_hash_lookup(ob->propstate_table,
2071 objprop_get_id(op), NULL);
2072}
2073
2074/************************************************************************/
2078 static bool objbind_has_modified_properties(struct objbind *ob)
2079{
2080 if (!ob) {
2081 return FALSE;
2082 }
2083
2084 return (0 < propstate_hash_size(ob->propstate_table));
2085}
2086
2087/************************************************************************/
2090 static void objbind_clear_all_modified_values(struct objbind *ob)
2091{
2092 if (!ob) {
2093 return;
2094 }
2095 propstate_hash_clear(ob->propstate_table);
2096}
2097
2098/************************************************************************/
2104 static bool objbind_set_modified_value(struct objbind *ob,
2105 struct objprop *op,
2106 struct propval *pv)
2107{
2108 struct propstate *ps;
2109 bool equal;
2110 struct propval *pv_old, *pv_copy;
2111 enum object_property_ids propid;
2112
2113 if (!ob || !op) {
2114 return FALSE;
2115 }
2116
2117 propid = objprop_get_id(op);
2118
2119 pv_old = objbind_get_value_from_object(ob, op);
2120 if (!pv_old) {
2121 return FALSE;
2122 }
2123
2124 equal = propval_equal(pv, pv_old);
2125 propval_free(pv_old);
2126
2127 if (equal) {
2128 objbind_clear_modified_value(ob, op);
2129 return FALSE;
2130 }
2131
2132 pv_copy = propval_copy(pv);
2133
2134 if (propstate_hash_lookup(ob->propstate_table, propid, &ps)) {
2135 propstate_set_value(ps, pv_copy);
2136 } else {
2137 ps = propstate_new(op, pv_copy);
2138 propstate_hash_insert(ob->propstate_table, propid, ps);
2139 }
2140
2141 return TRUE;
2142}
2143
2144/************************************************************************/
2150 static struct propval *objbind_get_modified_value(struct objbind *ob,
2151 struct objprop *op)
2152{
2153 struct propstate *ps;
2154
2155 if (!ob || !op) {
2156 return NULL;
2157 }
2158
2159 if (propstate_hash_lookup(ob->propstate_table, objprop_get_id(op), &ps)) {
2160 return propstate_get_value(ps);
2161 } else {
2162 return NULL;
2163 }
2164}
2165
2166/************************************************************************/
2169 static void objbind_destroy(struct objbind *ob)
2170{
2171 if (!ob) {
2172 return;
2173 }
2174 if (ob->propstate_table) {
2175 propstate_hash_destroy(ob->propstate_table);
2176 ob->propstate_table = NULL;
2177 }
2178 if (ob->rowref) {
2179 gtk_tree_row_reference_free(ob->rowref);
2180 ob->rowref = NULL;
2181 }
2182 free(ob);
2183}
2184
2185/************************************************************************/
2188 static enum editor_object_type objbind_get_objtype(const struct objbind *ob)
2189{
2190 if (!ob) {
2191 return NUM_OBJTYPES;
2192 }
2193 return ob->objtype;
2194}
2195
2196/************************************************************************/
2199 static void objbind_bind_properties(struct objbind *ob,
2200 struct property_page *pp)
2201{
2202 if (!ob) {
2203 return;
2204 }
2205 ob->parent_property_page = pp;
2206}
2207
2208/************************************************************************/
2213 static void objbind_pack_current_values(struct objbind *ob,
2214 union packetdata pd)
2215{
2216 enum editor_object_type objtype;
2217
2218 if (!ob || !pd.pointers.v_pointer1) {
2219 return;
2220 }
2221
2222 objtype = objbind_get_objtype(ob);
2223
2224 switch (objtype) {
2225 case OBJTYPE_TILE:
2226 {
2227 struct packet_edit_tile *packet = pd.tile;
2228 const struct tile *ptile = objbind_get_object(ob);
2229
2230 if (NULL == ptile) {
2231 return;
2232 }
2233
2234 packet->tile = tile_index(ptile);
2235 packet->extras = *tile_extras(ptile);
2236 /* TODO: Set more packet fields. */
2237 }
2238 return;
2239
2240 case OBJTYPE_STARTPOS:
2241 {
2242 struct packet_edit_startpos_full *packet = pd.startpos;
2243 const struct startpos *psp = objbind_get_object(ob);
2244
2245 if (NULL != psp) {
2246 startpos_pack(psp, packet);
2247 }
2248 }
2249 return;
2250
2251 case OBJTYPE_UNIT:
2252 {
2253 struct packet_edit_unit *packet = pd.unit;
2254 const struct unit *punit = objbind_get_object(ob);
2255
2256 if (NULL == punit) {
2257 return;
2258 }
2259
2260 packet->id32 = punit->id;
2261 packet->id16 = packet->id32;
2262 packet->moves_left = punit->moves_left;
2263 packet->fuel = punit->fuel;
2264 packet->moved = punit->moved;
2265 packet->done_moving = punit->done_moving;
2266 packet->hp = punit->hp;
2267 packet->veteran = punit->veteran;
2268 packet->stay = punit->stay;
2269 /* TODO: Set more packet fields. */
2270 }
2271 return;
2272
2273 case OBJTYPE_CITY:
2274 {
2275 struct packet_edit_city *packet = pd.city;
2276 const struct city *pcity = objbind_get_object(ob);
2277 int i;
2278
2279 if (NULL == pcity) {
2280 return;
2281 }
2282
2283 packet->id32 = pcity->id;
2284 packet->id16 = packet->id32;
2285 sz_strlcpy(packet->name, pcity->name);
2286 packet->size = city_size_get(pcity);
2287 packet->history = pcity->history;
2288 for (i = 0; i < B_LAST; i++) {
2289 packet->built[i] = pcity->built[i].turn;
2290 }
2291 packet->food_stock = pcity->food_stock;
2292 packet->shield_stock = pcity->shield_stock;
2293 /* TODO: Set more packet fields. */
2294 }
2295 return;
2296
2297 case OBJTYPE_PLAYER:
2298 {
2299 struct packet_edit_player *packet = pd.player;
2300 const struct player *pplayer = objbind_get_object(ob);
2301 const struct nation_type *pnation;
2302 const struct research *presearch;
2303
2304 if (NULL == pplayer) {
2305 return;
2306 }
2307
2308 packet->id = player_number(pplayer);
2309 sz_strlcpy(packet->name, pplayer->name);
2310 pnation = nation_of_player(pplayer);
2311 packet->nation = nation_index(pnation);
2312 presearch = research_get(pplayer);
2313 advance_index_iterate(A_FIRST, tech) {
2314 packet->inventions[tech]
2315 = TECH_KNOWN == research_invention_state(presearch, tech);
2316 } advance_index_iterate_end;
2317 packet->gold = pplayer->economic.gold;
2318 packet->government = government_index(pplayer->government);
2319 packet->scenario_reserved = player_has_flag(pplayer, PLRF_SCENARIO_RESERVED);
2320 /* TODO: Set more packet fields. */
2321 }
2322 return;
2323
2324 case OBJTYPE_GAME:
2325 {
2326 struct packet_edit_game *packet = pd.game.game;
2327 const struct civ_game *pgame = objbind_get_object(ob);
2328
2329 if (NULL == pgame) {
2330 return;
2331 }
2332
2333 packet->scenario = pgame->scenario.is_scenario;
2334 sz_strlcpy(packet->scenario_name, pgame->scenario.name);
2335 sz_strlcpy(packet->scenario_authors, pgame->scenario.authors);
2336 sz_strlcpy(pd.game.desc->scenario_desc, pgame->scenario_desc.description);
2337 packet->scenario_random = pgame->scenario.save_random;
2338 packet->scenario_players = pgame->scenario.players;
2339 packet->startpos_nations = pgame->scenario.startpos_nations;
2340 packet->prevent_new_cities = pgame->scenario.prevent_new_cities;
2341 packet->lake_flooding = pgame->scenario.lake_flooding;
2342 }
2343 return;
2344
2345 case NUM_OBJTYPES:
2346 break;
2347 }
2348
2349 log_error("%s(): Unhandled object type %s (nb %d).", __FUNCTION__,
2350 objtype_get_name(objtype), objtype);
2351}
2352
2353/************************************************************************/
2356 static void objbind_pack_modified_value(struct objbind *ob,
2357 struct objprop *op,
2358 union packetdata pd)
2359{
2360 struct propval *pv;
2361 enum editor_object_type objtype;
2362 enum object_property_ids propid;
2363
2364 if (!op || !ob || !pd.pointers.v_pointer1) {
2365 return;
2366 }
2367
2368 if (NULL == objbind_get_object(ob)) {
2369 return;
2370 }
2371
2372 if (objprop_is_readonly(op) || !objbind_property_is_modified(ob, op)) {
2373 return;
2374 }
2375
2376 pv = objbind_get_modified_value(ob, op);
2377 if (!pv) {
2378 return;
2379 }
2380
2381 objtype = objbind_get_objtype(ob);
2382 propid = objprop_get_id(op);
2383
2384 switch (objtype) {
2385 case OBJTYPE_TILE:
2386 {
2387 struct packet_edit_tile *packet = pd.tile;
2388
2389 switch (propid) {
2390 case OPID_TILE_SPECIALS:
2391 extra_type_by_cause_iterate(EC_SPECIAL, pextra) {
2392 if (BV_ISSET(pv->data.v_bv_special, pextra->data.special_idx)) {
2393 BV_SET(packet->extras, pextra->data.special_idx);
2394 } else {
2395 BV_CLR(packet->extras, pextra->data.special_idx);
2396 }
2397 } extra_type_by_cause_iterate_end;
2398 return;
2399 case OPID_TILE_ROADS:
2400 extra_type_by_cause_iterate(EC_ROAD, pextra) {
2401 int ridx = road_number(extra_road_get(pextra));
2402
2403 if (BV_ISSET(pv->data.v_bv_roads, ridx)) {
2404 BV_SET(packet->extras, extra_index(pextra));
2405 } else {
2406 BV_CLR(packet->extras, extra_index(pextra));
2407 }
2408 } extra_type_by_cause_iterate_end;
2409 return;
2410 case OPID_TILE_BASES:
2411 extra_type_by_cause_iterate(EC_BASE, pextra) {
2412 int bidx = base_number(extra_base_get(pextra));
2413
2414 if (BV_ISSET(pv->data.v_bv_bases, bidx)) {
2415 BV_SET(packet->extras, extra_index(pextra));
2416 } else {
2417 BV_CLR(packet->extras, extra_index(pextra));
2418 }
2419 } extra_type_by_cause_iterate_end;
2420 return;
2421 case OPID_TILE_LABEL:
2422 sz_strlcpy(packet->label, pv->data.v_string);
2423 return;
2424 default:
2425 break;
2426 }
2427 }
2428 log_error("%s(): Unhandled request to pack value of property "
2429 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2430 propid, objprop_get_name(op), objtype_get_name(objtype));
2431 return;
2432
2433 case OBJTYPE_STARTPOS:
2434 {
2435 struct packet_edit_startpos_full *packet = pd.startpos;
2436
2437 switch (propid) {
2438 case OPID_STARTPOS_EXCLUDE:
2439 packet->exclude = pv->data.v_bool;
2440 return;
2441 case OPID_STARTPOS_NATIONS:
2442 BV_CLR_ALL(packet->nations);
2443 nation_hash_iterate(pv->data.v_nation_hash, pnation) {
2444 BV_SET(packet->nations, nation_number(pnation));
2445 } nation_hash_iterate_end;
2446 return;
2447 default:
2448 break;
2449 }
2450 }
2451 log_error("%s(): Unhandled request to pack value of property "
2452 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2453 propid, objprop_get_name(op), objtype_get_name(objtype));
2454 return;
2455
2456 case OBJTYPE_UNIT:
2457 {
2458 struct packet_edit_unit *packet = pd.unit;
2459
2460 switch (propid) {
2461 case OPID_UNIT_MOVES_LEFT:
2462 packet->moves_left = pv->data.v_int;
2463 return;
2464 case OPID_UNIT_FUEL:
2465 packet->fuel = pv->data.v_int;
2466 return;
2467 case OPID_UNIT_MOVED:
2468 packet->moved = pv->data.v_bool;
2469 return;
2470 case OPID_UNIT_DONE_MOVING:
2471 packet->done_moving = pv->data.v_bool;
2472 return;
2473 case OPID_UNIT_HP:
2474 packet->hp = pv->data.v_int;
2475 return;
2476 case OPID_UNIT_VETERAN:
2477 packet->veteran = pv->data.v_int;
2478 return;
2479 case OPID_UNIT_STAY:
2480 packet->stay = pv->data.v_bool;
2481 return;
2482 default:
2483 break;
2484 }
2485 }
2486 log_error("%s(): Unhandled request to pack value of property "
2487 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2488 propid, objprop_get_name(op), objtype_get_name(objtype));
2489 return;
2490
2491 case OBJTYPE_CITY:
2492 {
2493 struct packet_edit_city *packet = pd.city;
2494
2495 switch (propid) {
2496 case OPID_CITY_NAME:
2497 sz_strlcpy(packet->name, pv->data.v_string);
2498 return;
2499 case OPID_CITY_SIZE:
2500 packet->size = pv->data.v_int;
2501 return;
2502 case OPID_CITY_HISTORY:
2503 packet->history = pv->data.v_int;
2504 return;
2505 case OPID_CITY_FOOD_STOCK:
2506 packet->food_stock = pv->data.v_int;
2507 return;
2508 case OPID_CITY_SHIELD_STOCK:
2509 packet->shield_stock = pv->data.v_int;
2510 return;
2511 case OPID_CITY_BUILDINGS:
2512 {
2513 int i;
2514
2515 for (i = 0; i < B_LAST; i++) {
2516 packet->built[i] = pv->data.v_built[i].turn;
2517 }
2518 }
2519 return;
2520 default:
2521 break;
2522 }
2523 }
2524 log_error("%s(): Unhandled request to pack value of property "
2525 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2526 propid, objprop_get_name(op), objtype_get_name(objtype));
2527 return;
2528
2529 case OBJTYPE_PLAYER:
2530 {
2531 struct packet_edit_player *packet = pd.player;
2532
2533 switch (propid) {
2534 case OPID_PLAYER_NAME:
2535 sz_strlcpy(packet->name, pv->data.v_string);
2536 return;
2537 case OPID_PLAYER_NATION:
2538 packet->nation = nation_index(pv->data.v_nation);
2539 return;
2540 case OPID_PLAYER_GOV:
2541 packet->government = government_index(pv->data.v_gov);
2542 return;
2543 case OPID_PLAYER_INVENTIONS:
2544 advance_index_iterate(A_FIRST, tech) {
2545 packet->inventions[tech] = BV_ISSET(pv->data.v_bv_inventions, tech);
2546 } advance_index_iterate_end;
2547 return;
2548 case OPID_PLAYER_SCENARIO_RESERVED:
2549 packet->scenario_reserved = pv->data.v_bool;
2550 return;
2551 case OPID_PLAYER_SCIENCE:
2552 packet->bulbs_researched = pv->data.v_int;
2553 return;
2554 case OPID_PLAYER_GOLD:
2555 packet->gold = pv->data.v_int;
2556 return;
2557 default:
2558 break;
2559 }
2560 }
2561 log_error("%s(): Unhandled request to pack value of property "
2562 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2563 propid, objprop_get_name(op), objtype_get_name(objtype));
2564 return;
2565
2566 case OBJTYPE_GAME:
2567 {
2568 struct packet_edit_game *packet = pd.game.game;
2569
2570 switch (propid) {
2571 case OPID_GAME_SCENARIO:
2572 packet->scenario = pv->data.v_bool;
2573 return;
2574 case OPID_GAME_SCENARIO_NAME:
2575 sz_strlcpy(packet->scenario_name, pv->data.v_const_string);
2576 return;
2577 case OPID_GAME_SCENARIO_AUTHORS:
2578 sz_strlcpy(packet->scenario_authors, pv->data.v_const_string);
2579 return;
2580 case OPID_GAME_SCENARIO_DESC:
2581 sz_strlcpy(pd.game.desc->scenario_desc, pv->data.v_const_string);
2582 return;
2583 case OPID_GAME_SCENARIO_RANDSTATE:
2584 packet->scenario_random = pv->data.v_bool;
2585 return;
2586 case OPID_GAME_SCENARIO_PLAYERS:
2587 packet->scenario_players = pv->data.v_bool;
2588 return;
2589 case OPID_GAME_STARTPOS_NATIONS:
2590 packet->startpos_nations = pv->data.v_bool;
2591 return;
2592 case OPID_GAME_PREVENT_CITIES:
2593 packet->prevent_new_cities = pv->data.v_bool;
2594 return;
2595 case OPID_GAME_LAKE_FLOODING:
2596 packet->lake_flooding = pv->data.v_bool;
2597 return;
2598 case OPID_GAME_RULESET_LOCKED:
2599 packet->ruleset_locked = pv->data.v_bool;
2600 return;
2601 default:
2602 break;
2603 }
2604 }
2605 log_error("%s(): Unhandled request to pack value of property "
2606 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2607 propid, objprop_get_name(op), objtype_get_name(objtype));
2608 return;
2609
2610 case NUM_OBJTYPES:
2611 break;
2612 }
2613
2614 log_error("%s(): Unhandled request for object type \"%s\" (nb %d).",
2615 __FUNCTION__, objtype_get_name(objtype), objtype);
2616
2617}
2618
2619/************************************************************************/
2622 static void objbind_set_rowref(struct objbind *ob,
2623 GtkTreeRowReference *rr)
2624{
2625 if (!ob) {
2626 return;
2627 }
2628 ob->rowref = rr;
2629}
2630
2631/************************************************************************/
2634 static GtkTreeRowReference *objbind_get_rowref(struct objbind *ob)
2635{
2636 if (!ob) {
2637 return NULL;
2638 }
2639 return ob->rowref;
2640}
2641
2642/************************************************************************/
2645 static int objprop_get_id(const struct objprop *op)
2646{
2647 if (!op) {
2648 return -1;
2649 }
2650 return op->id;
2651}
2652
2653/************************************************************************/
2660 static GType objprop_get_gtype(const struct objprop *op)
2661{
2662 fc_assert_ret_val(NULL != op, G_TYPE_NONE);
2663
2664 switch (op->valtype) {
2665 case VALTYPE_NONE:
2666 case VALTYPE_TILE_VISION_DATA:
2667 return G_TYPE_NONE;
2668 case VALTYPE_INT:
2669 return G_TYPE_INT;
2670 case VALTYPE_BOOL:
2671 /* We want to show it as translated string, not as untranslated G_TYPE_BOOLEAN */
2672 return G_TYPE_STRING;
2673 case VALTYPE_STRING:
2674 case VALTYPE_BUILT_ARRAY:
2675 case VALTYPE_INVENTIONS_ARRAY:
2676 case VALTYPE_BV_SPECIAL:
2677 case VALTYPE_BV_ROADS:
2678 case VALTYPE_BV_BASES:
2679 case VALTYPE_NATION_HASH:
2680 return G_TYPE_STRING;
2681 case VALTYPE_PIXBUF:
2682 case VALTYPE_NATION:
2683 case VALTYPE_GOV:
2684 return GDK_TYPE_PIXBUF;
2685 }
2686 log_error("%s(): Unhandled value type %d.", __FUNCTION__, op->valtype);
2687 return G_TYPE_NONE;
2688}
2689
2690/************************************************************************/
2693 static enum value_types objprop_get_valtype(const struct objprop *op)
2694{
2695 if (!op) {
2696 return VALTYPE_NONE;
2697 }
2698 return op->valtype;
2699}
2700
2701/************************************************************************/
2704 static bool objprop_show_in_listview(const struct objprop *op)
2705{
2706 if (!op) {
2707 return FALSE;
2708 }
2709 return op->flags & OPF_IN_LISTVIEW;
2710}
2711
2712/************************************************************************/
2715 static bool objprop_has_widget(const struct objprop *op)
2716{
2717 if (!op) {
2718 return FALSE;
2719 }
2720 return op->flags & OPF_HAS_WIDGET;
2721}
2722
2723/************************************************************************/
2729 static const char *objprop_get_attribute_type_string(const struct objprop *op)
2730{
2731 GType gtype;
2732
2733 if (!op) {
2734 return NULL;
2735 }
2736
2737 gtype = objprop_get_gtype(op);
2738 if (gtype == G_TYPE_INT || gtype == G_TYPE_STRING
2739 || gtype == G_TYPE_BOOLEAN) {
2740 return "text";
2741 } else if (gtype == GDK_TYPE_PIXBUF) {
2742 return "pixbuf";
2743 }
2744
2745 return NULL;
2746}
2747
2748/************************************************************************/
2754 static void objprop_set_column_id(struct objprop *op, int col_id)
2755{
2756 if (!op) {
2757 return;
2758 }
2759 op->column_id = col_id;
2760}
2761
2762/************************************************************************/
2767 static int objprop_get_column_id(const struct objprop *op)
2768{
2769 if (!op) {
2770 return -1;
2771 }
2772 return op->column_id;
2773}
2774
2775/************************************************************************/
2778 static void objprop_set_treeview_column(struct objprop *op,
2779 GtkTreeViewColumn *col)
2780{
2781 if (!op) {
2782 return;
2783 }
2784 op->view_column = col;
2785}
2786
2787/************************************************************************/
2791 static GtkTreeViewColumn *objprop_get_treeview_column(const struct objprop *op)
2792{
2793 if (!op) {
2794 return NULL;
2795 }
2796 return op->view_column;
2797}
2798
2799/************************************************************************/
2802 static const char *objprop_get_name(const struct objprop *op)
2803{
2804 if (!op) {
2805 return NULL;
2806 }
2807 return op->name;
2808}
2809
2810/************************************************************************/
2813 static const char *objprop_get_tooltip(const struct objprop *op)
2814{
2815 if (!op) {
2816 return NULL;
2817 }
2818 return op->tooltip;
2819}
2820
2821/************************************************************************/
2826 static GtkCellRenderer *objprop_create_cell_renderer(const struct objprop *op)
2827{
2828 GtkCellRenderer *cell = NULL;
2829 GType gtype;
2830
2831 gtype = objprop_get_gtype(op);
2832
2833 if (gtype == G_TYPE_INT || gtype == G_TYPE_STRING
2834 || gtype == G_TYPE_BOOLEAN) {
2835 cell = gtk_cell_renderer_text_new();
2836 } else if (gtype == GDK_TYPE_PIXBUF) {
2837 cell = gtk_cell_renderer_pixbuf_new();
2838 }
2839
2840 return cell;
2841}
2842
2843/************************************************************************/
2847 static bool objprop_is_sortable(const struct objprop *op)
2848{
2849 GType gtype;
2850 if (!op) {
2851 return FALSE;
2852 }
2853 gtype = objprop_get_gtype(op);
2854 return gtype == G_TYPE_INT || gtype == G_TYPE_STRING;
2855}
2856
2857/************************************************************************/
2861 static bool objprop_is_readonly(const struct objprop *op)
2862{
2863 if (!op) {
2864 return TRUE;
2865 }
2866 return !(op->flags & OPF_EDITABLE);
2867}
2868
2869/************************************************************************/
2872 static void objprop_widget_entry_changed(GtkEntry *entry, gpointer userdata)
2873{
2874 struct objprop *op;
2875 struct property_page *pp;
2876 struct propval value = {{0,}, VALTYPE_STRING, FALSE};
2877
2878 op = userdata;
2879 pp = objprop_get_property_page(op);
2880 value.data.v_const_string = gtk_entry_get_text(entry);
2881
2882 property_page_change_value(pp, op, &value);
2883}
2884
2885/************************************************************************/
2888 static void objprop_widget_spin_button_changed(GtkSpinButton *spin,
2889 gpointer userdata)
2890{
2891 struct objprop *op;
2892 struct property_page *pp;
2893 struct propval value = {{0,}, VALTYPE_INT, FALSE};
2894
2895 op = userdata;
2896 pp = objprop_get_property_page(op);
2897 value.data.v_int = gtk_spin_button_get_value_as_int(spin);
2898
2899 property_page_change_value(pp, op, &value);
2900}
2901
2902/************************************************************************/
2905 static void objprop_widget_toggle_button_changed(GtkToggleButton *button,
2906 gpointer userdata)
2907{
2908 struct objprop *op;
2909 struct property_page *pp;
2910 struct propval value = {{0,}, VALTYPE_BOOL, FALSE};
2911
2912 op = userdata;
2913 pp = objprop_get_property_page(op);
2914 value.data.v_bool = gtk_toggle_button_get_active(button);
2915
2916 property_page_change_value(pp, op, &value);
2917}
2918
2919/************************************************************************/
2922 static void objprop_setup_widget(struct objprop *op)
2923{
2924 GtkWidget *ebox, *hbox, *hbox2, *label, *image, *entry, *spin, *button;
2925 struct extviewer *ev = NULL;
2926 enum object_property_ids propid;
2927
2928 if (!op) {
2929 return;
2930 }
2931
2932 if (!objprop_has_widget(op)) {
2933 return;
2934 }
2935
2936 ebox = gtk_event_box_new();
2937 op->widget = ebox;
2938
2939 hbox = gtk_grid_new();
2940 gtk_grid_set_column_spacing(GTK_GRID(hbox), 4);
2941
2942 gtk_container_add(GTK_CONTAINER(ebox), hbox);
2943
2944 label = gtk_label_new(objprop_get_name(op));
2945 gtk_widget_set_halign(label, GTK_ALIGN_START);
2946 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
2947 gtk_container_add(GTK_CONTAINER(hbox), label);
2948 objprop_set_child_widget(op, "name-label", label);
2949
2950 propid = objprop_get_id(op);
2951
2952 switch (propid) {
2953 case OPID_TILE_INDEX:
2954 case OPID_TILE_X:
2955 case OPID_TILE_Y:
2956 case OPID_TILE_NAT_X:
2957 case OPID_TILE_NAT_Y:
2958 case OPID_TILE_CONTINENT:
2959 case OPID_TILE_TERRAIN:
2960 case OPID_TILE_RESOURCE:
2961 case OPID_TILE_XY:
2962 case OPID_STARTPOS_XY:
2963 case OPID_UNIT_ID:
2964 case OPID_UNIT_XY:
2965 case OPID_UNIT_TYPE:
2966 case OPID_CITY_ID:
2967 case OPID_CITY_XY:
2968 case OPID_PLAYER_AGE:
2969#ifdef FREECIV_DEBUG
2970 case OPID_TILE_ADDRESS:
2971 case OPID_UNIT_ADDRESS:
2972 case OPID_CITY_ADDRESS:
2973 case OPID_PLAYER_ADDRESS:
2974#endif /* FREECIV_DEBUG */
2975 label = gtk_label_new(NULL);
2976 gtk_widget_set_hexpand(label, TRUE);
2977 gtk_widget_set_halign(label, GTK_ALIGN_START);
2978 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
2979 gtk_container_add(GTK_CONTAINER(hbox), label);
2980 objprop_set_child_widget(op, "value-label", label);
2981 return;
2982
2983 case OPID_TILE_IMAGE:
2984 case OPID_STARTPOS_IMAGE:
2985 case OPID_UNIT_IMAGE:
2986 case OPID_CITY_IMAGE:
2987 image = gtk_image_new();
2988 gtk_widget_set_hexpand(image, TRUE);
2989 gtk_widget_set_halign(image, GTK_ALIGN_START);
2990 gtk_widget_set_valign(image, GTK_ALIGN_CENTER);
2991 gtk_container_add(GTK_CONTAINER(hbox), image);
2992 objprop_set_child_widget(op, "image", image);
2993 return;
2994
2995 case OPID_CITY_NAME:
2996 case OPID_PLAYER_NAME:
2997 case OPID_GAME_SCENARIO_NAME:
2998 case OPID_TILE_LABEL:
2999 entry = gtk_entry_new();
3000 gtk_widget_set_hexpand(entry, TRUE);
3001 gtk_widget_set_halign(entry, GTK_ALIGN_END);
3002 gtk_entry_set_width_chars(GTK_ENTRY(entry), 8);
3003 g_signal_connect(entry, "changed",
3004 G_CALLBACK(objprop_widget_entry_changed), op);
3005 gtk_container_add(GTK_CONTAINER(hbox), entry);
3006 objprop_set_child_widget(op, "entry", entry);
3007 return;
3008
3009 case OPID_UNIT_MOVES_LEFT:
3010 case OPID_CITY_SIZE:
3011 case OPID_CITY_HISTORY:
3012 case OPID_CITY_SHIELD_STOCK:
3013 case OPID_PLAYER_SCIENCE:
3014 case OPID_PLAYER_GOLD:
3015 spin = gtk_spin_button_new_with_range(0.0, 100.0, 1.0);
3016 gtk_widget_set_hexpand(spin, TRUE);
3017 gtk_widget_set_halign(spin, GTK_ALIGN_END);
3018 g_signal_connect(spin, "value-changed",
3019 G_CALLBACK(objprop_widget_spin_button_changed), op);
3020 gtk_container_add(GTK_CONTAINER(hbox), spin);
3021 objprop_set_child_widget(op, "spin", spin);
3022 return;
3023
3024 case OPID_UNIT_FUEL:
3025 case OPID_UNIT_HP:
3026 case OPID_UNIT_VETERAN:
3027 case OPID_CITY_FOOD_STOCK:
3028 hbox2 = gtk_grid_new();
3029 gtk_widget_set_hexpand(hbox2, TRUE);
3030 gtk_widget_set_halign(hbox2, GTK_ALIGN_END);
3031 gtk_grid_set_column_spacing(GTK_GRID(hbox2), 4);
3032 gtk_container_add(GTK_CONTAINER(hbox), hbox2);
3033 spin = gtk_spin_button_new_with_range(0.0, 100.0, 1.0);
3034 g_signal_connect(spin, "value-changed",
3035 G_CALLBACK(objprop_widget_spin_button_changed), op);
3036 gtk_container_add(GTK_CONTAINER(hbox2), spin);
3037 objprop_set_child_widget(op, "spin", spin);
3038 label = gtk_label_new(NULL);
3039 gtk_widget_set_halign(label, GTK_ALIGN_START);
3040 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
3041 gtk_container_add(GTK_CONTAINER(hbox2), label);
3042 objprop_set_child_widget(op, "max-value-label", label);
3043 return;
3044
3045 case OPID_TILE_SPECIALS:
3046 case OPID_TILE_ROADS:
3047 case OPID_TILE_BASES:
3048 case OPID_TILE_VISION:
3049 case OPID_STARTPOS_NATIONS:
3050 case OPID_CITY_BUILDINGS:
3051 case OPID_PLAYER_NATION:
3052 case OPID_PLAYER_GOV:
3053 case OPID_PLAYER_INVENTIONS:
3054 case OPID_GAME_SCENARIO_AUTHORS:
3055 case OPID_GAME_SCENARIO_DESC:
3056 ev = extviewer_new(op);
3057 objprop_set_extviewer(op, ev);
3058 gtk_widget_set_hexpand(extviewer_get_panel_widget(ev), TRUE);
3059 gtk_widget_set_halign(extviewer_get_panel_widget(ev), GTK_ALIGN_END);
3060 gtk_container_add(GTK_CONTAINER(hbox), extviewer_get_panel_widget(ev));
3061 property_page_add_extviewer(objprop_get_property_page(op), ev);
3062 return;
3063
3064 case OPID_STARTPOS_EXCLUDE:
3065 case OPID_UNIT_MOVED:
3066 case OPID_UNIT_DONE_MOVING:
3067 case OPID_UNIT_STAY:
3068 case OPID_GAME_SCENARIO:
3069 case OPID_GAME_SCENARIO_RANDSTATE:
3070 case OPID_GAME_SCENARIO_PLAYERS:
3071 case OPID_GAME_STARTPOS_NATIONS:
3072 case OPID_GAME_PREVENT_CITIES:
3073 case OPID_GAME_LAKE_FLOODING:
3074 case OPID_GAME_RULESET_LOCKED:
3075 case OPID_PLAYER_SCENARIO_RESERVED:
3076 button = gtk_check_button_new();
3077 gtk_widget_set_hexpand(button, TRUE);
3078 gtk_widget_set_halign(button, GTK_ALIGN_END);
3079 g_signal_connect(button, "toggled",
3080 G_CALLBACK(objprop_widget_toggle_button_changed), op);
3081 gtk_container_add(GTK_CONTAINER(hbox), button);
3082 objprop_set_child_widget(op, "checkbutton", button);
3083 return;
3084 }
3085
3086 log_error("%s(): Unhandled request to create widget for property %d (%s).",
3087 __FUNCTION__, propid, objprop_get_name(op));
3088}
3089
3090/************************************************************************/
3098 static void objprop_refresh_widget(struct objprop *op,
3099 struct objbind *ob)
3100{
3101 GtkWidget *w, *label, *image, *entry, *spin, *button;
3102 struct extviewer *ev;
3103 struct propval *pv;
3104 bool modified;
3105 enum object_property_ids propid;
3106 double min, max, step, big_step;
3107 char buf[256];
3108
3109 if (!op || !objprop_has_widget(op)) {
3110 return;
3111 }
3112
3113 w = objprop_get_widget(op);
3114 if (!w) {
3115 return;
3116 }
3117
3118 propid = objprop_get_id(op);
3119
3120 /* NB: We must take care to propval_free the return value of
3121 * objbind_get_value_from_object(), since it always makes a
3122 * copy, but to NOT free the result of objbind_get_modified_value()
3123 * since it returns its own stored value. */
3124 pv = objbind_get_value_from_object(ob, op);
3125 modified = objbind_property_is_modified(ob, op);
3126
3127 if (pv && modified) {
3128 struct propval *pv_mod;
3129
3130 pv_mod = objbind_get_modified_value(ob, op);
3131 if (pv_mod) {
3132 if (propval_equal(pv, pv_mod)) {
3133 objbind_clear_modified_value(ob, op);
3134 modified = FALSE;
3135 } else {
3136 propval_free(pv);
3137 pv = pv_mod;
3138 modified = TRUE;
3139 }
3140 } else {
3141 modified = FALSE;
3142 }
3143 }
3144
3145 switch (propid) {
3146 case OPID_TILE_IMAGE:
3147 case OPID_STARTPOS_IMAGE:
3148 case OPID_UNIT_IMAGE:
3149 case OPID_CITY_IMAGE:
3150 image = objprop_get_child_widget(op, "image");
3151 if (pv) {
3152 gtk_image_set_from_pixbuf(GTK_IMAGE(image), pv->data.v_pixbuf);
3153 } else {
3154 gtk_image_set_from_pixbuf(GTK_IMAGE(image), NULL);
3155 }
3156 break;
3157
3158 case OPID_TILE_XY:
3159 case OPID_TILE_TERRAIN:
3160 case OPID_TILE_RESOURCE:
3161 case OPID_STARTPOS_XY:
3162 case OPID_UNIT_XY:
3163 case OPID_UNIT_TYPE:
3164 case OPID_CITY_XY:
3165#ifdef FREECIV_DEBUG
3166 case OPID_TILE_ADDRESS:
3167 case OPID_UNIT_ADDRESS:
3168 case OPID_CITY_ADDRESS:
3169 case OPID_PLAYER_ADDRESS:
3170#endif /* FREECIV_DEBUG */
3171 label = objprop_get_child_widget(op, "value-label");
3172 if (pv) {
3173 gtk_label_set_text(GTK_LABEL(label), pv->data.v_string);
3174 } else {
3175 gtk_label_set_text(GTK_LABEL(label), NULL);
3176 }
3177 break;
3178
3179 case OPID_TILE_INDEX:
3180 case OPID_TILE_X:
3181 case OPID_TILE_Y:
3182 case OPID_TILE_NAT_X:
3183 case OPID_TILE_NAT_Y:
3184 case OPID_TILE_CONTINENT:
3185 case OPID_UNIT_ID:
3186 case OPID_CITY_ID:
3187 case OPID_PLAYER_AGE:
3188 label = objprop_get_child_widget(op, "value-label");
3189 if (pv) {
3190 char agebuf[16];
3191
3192 fc_snprintf(agebuf, sizeof(agebuf), "%d", pv->data.v_int);
3193 gtk_label_set_text(GTK_LABEL(label), agebuf);
3194 } else {
3195 gtk_label_set_text(GTK_LABEL(label), NULL);
3196 }
3197 break;
3198
3199 case OPID_CITY_NAME:
3200 case OPID_PLAYER_NAME:
3201 case OPID_GAME_SCENARIO_NAME:
3202 case OPID_TILE_LABEL:
3203 entry = objprop_get_child_widget(op, "entry");
3204 if (pv) {
3205 gtk_entry_set_text(GTK_ENTRY(entry), pv->data.v_string);
3206 } else {
3207 gtk_entry_set_text(GTK_ENTRY(entry), "");
3208 }
3209 gtk_widget_set_sensitive(entry, pv != NULL);
3210 break;
3211
3212 case OPID_UNIT_MOVES_LEFT:
3213 case OPID_CITY_SIZE:
3214 case OPID_CITY_HISTORY:
3215 case OPID_CITY_SHIELD_STOCK:
3216 case OPID_PLAYER_SCIENCE:
3217 case OPID_PLAYER_GOLD:
3218 spin = objprop_get_child_widget(op, "spin");
3219 if (pv) {
3220 disable_gobject_callback(G_OBJECT(spin),
3221 G_CALLBACK(objprop_widget_spin_button_changed));
3222 if (objbind_get_allowed_value_span(ob, op, &min, &max,
3223 &step, &big_step)) {
3224 gtk_spin_button_set_range(GTK_SPIN_BUTTON(spin), min, max);
3225 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(spin),
3226 step, big_step);
3227 }
3228 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), pv->data.v_int);
3229 enable_gobject_callback(G_OBJECT(spin),
3230 G_CALLBACK(objprop_widget_spin_button_changed));
3231 }
3232 gtk_widget_set_sensitive(spin, pv != NULL);
3233 break;
3234
3235 case OPID_UNIT_FUEL:
3236 case OPID_UNIT_HP:
3237 case OPID_UNIT_VETERAN:
3238 case OPID_CITY_FOOD_STOCK:
3239 spin = objprop_get_child_widget(op, "spin");
3240 label = objprop_get_child_widget(op, "max-value-label");
3241 if (pv) {
3242 disable_gobject_callback(G_OBJECT(spin),
3243 G_CALLBACK(objprop_widget_spin_button_changed));
3244 if (objbind_get_allowed_value_span(ob, op, &min, &max,
3245 &step, &big_step)) {
3246 gtk_spin_button_set_range(GTK_SPIN_BUTTON(spin), min, max);
3247 gtk_spin_button_set_increments(GTK_SPIN_BUTTON(spin),
3248 step, big_step);
3249 fc_snprintf(buf, sizeof(buf), "/%d", (int) max);
3250 gtk_label_set_text(GTK_LABEL(label), buf);
3251 } else {
3252 gtk_label_set_text(GTK_LABEL(label), NULL);
3253 }
3254 gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin), pv->data.v_int);
3255 enable_gobject_callback(G_OBJECT(spin),
3256 G_CALLBACK(objprop_widget_spin_button_changed));
3257 } else {
3258 gtk_label_set_text(GTK_LABEL(label), NULL);
3259 }
3260 gtk_widget_set_sensitive(spin, pv != NULL);
3261 break;
3262
3263 case OPID_TILE_SPECIALS:
3264 case OPID_TILE_ROADS:
3265 case OPID_TILE_BASES:
3266 case OPID_TILE_VISION:
3267 case OPID_STARTPOS_NATIONS:
3268 case OPID_CITY_BUILDINGS:
3269 case OPID_PLAYER_NATION:
3270 case OPID_PLAYER_GOV:
3271 case OPID_PLAYER_INVENTIONS:
3272 case OPID_GAME_SCENARIO_AUTHORS:
3273 case OPID_GAME_SCENARIO_DESC:
3274 ev = objprop_get_extviewer(op);
3275 if (pv) {
3276 extviewer_refresh_widgets(ev, pv);
3277 } else {
3278 extviewer_clear_widgets(ev);
3279 }
3280 break;
3281
3282 case OPID_STARTPOS_EXCLUDE:
3283 case OPID_UNIT_MOVED:
3284 case OPID_UNIT_DONE_MOVING:
3285 case OPID_UNIT_STAY:
3286 case OPID_GAME_SCENARIO:
3287 case OPID_GAME_SCENARIO_RANDSTATE:
3288 case OPID_GAME_SCENARIO_PLAYERS:
3289 case OPID_GAME_STARTPOS_NATIONS:
3290 case OPID_GAME_PREVENT_CITIES:
3291 case OPID_GAME_LAKE_FLOODING:
3292 case OPID_GAME_RULESET_LOCKED:
3293 case OPID_PLAYER_SCENARIO_RESERVED:
3294 button = objprop_get_child_widget(op, "checkbutton");
3295 disable_gobject_callback(G_OBJECT(button),
3296 G_CALLBACK(objprop_widget_toggle_button_changed));
3297 if (pv) {
3298 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
3299 pv->data.v_bool);
3300 } else {
3301 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
3302 }
3303 enable_gobject_callback(G_OBJECT(button),
3304 G_CALLBACK(objprop_widget_toggle_button_changed));
3305 gtk_widget_set_sensitive(button, pv != NULL);
3306 break;
3307 }
3308
3309 if (!modified) {
3310 propval_free(pv);
3311 }
3312
3313 label = objprop_get_child_widget(op, "name-label");
3314 if (label) {
3315 const char *name = objprop_get_name(op);
3316 if (modified) {
3317 char namebuf[128];
3318
3319 fc_snprintf(namebuf, sizeof(namebuf),
3320 "<span foreground=\"red\">%s</span>", name);
3321 gtk_label_set_markup(GTK_LABEL(label), namebuf);
3322 } else {
3323 gtk_label_set_text(GTK_LABEL(label), name);
3324 }
3325 }
3326}
3327
3328/************************************************************************/
3332 static GtkWidget *objprop_get_widget(struct objprop *op)
3333{
3334 if (!op) {
3335 return NULL;
3336 }
3337 if (!op->widget) {
3338 objprop_setup_widget(op);
3339 }
3340 return op->widget;
3341}
3342
3343/************************************************************************/
3347 static void objprop_set_child_widget(struct objprop *op,
3348 const char *widget_name,
3349 GtkWidget *widget)
3350{
3351 GtkWidget *w;
3352
3353 if (!op || !widget_name || !widget) {
3354 return;
3355 }
3356
3357 w = objprop_get_widget(op);
3358 if (!w) {
3359 log_error("Cannot store child widget %p under name "
3360 "\"%s\" using objprop_set_child_widget for object "
3361 "property %d (%s) because objprop_get_widget does "
3362 "not return a valid widget.",
3363 widget, widget_name, objprop_get_id(op), objprop_get_name(op));
3364 return;
3365 }
3366
3367 g_object_set_data(G_OBJECT(w), widget_name, widget);
3368}
3369
3370/************************************************************************/
3374 static GtkWidget *objprop_get_child_widget(struct objprop *op,
3375 const char *widget_name)
3376{
3377 GtkWidget *w, *child;
3378
3379 if (!op || !widget_name) {
3380 return NULL;
3381 }
3382
3383 w = objprop_get_widget(op);
3384 if (!w) {
3385 log_error("Cannot retrieve child widget under name "
3386 "\"%s\" using objprop_get_child_widget for object "
3387 "property %d (%s) because objprop_get_widget does "
3388 "not return a valid widget.",
3389 widget_name, objprop_get_id(op), objprop_get_name(op));
3390 return NULL;
3391 }
3392
3393 child = g_object_get_data(G_OBJECT(w), widget_name);
3394 if (!child) {
3395 log_error("Child widget \"%s\" not found for object "
3396 "property %d (%s) via objprop_get_child_widget.",
3397 widget_name, objprop_get_id(op), objprop_get_name(op));
3398 return NULL;
3399 }
3400
3401 return child;
3402}
3403
3404/************************************************************************/
3407 static void objprop_set_extviewer(struct objprop *op,
3408 struct extviewer *ev)
3409{
3410 if (!op) {
3411 return;
3412 }
3413 op->extviewer = ev;
3414}
3415
3416/************************************************************************/
3419 static struct extviewer *objprop_get_extviewer(struct objprop *op)
3420{
3421 if (!op) {
3422 return NULL;
3423 }
3424 return op->extviewer;
3425}
3426
3427/************************************************************************/
3430 static struct property_page *objprop_get_property_page(const struct objprop *op)
3431{
3432 if (!op) {
3433 return NULL;
3434 }
3435 return op->parent_page;
3436}
3437
3438/************************************************************************/
3441 static struct objprop *objprop_new(int id,
3442 const char *name,
3443 const char *tooltip,
3444 enum object_property_flags flags,
3445 enum value_types valtype,
3446 struct property_page *parent)
3447{
3448 struct objprop *op;
3449
3450 op = fc_calloc(1, sizeof(*op));
3451 op->id = id;
3452 op->name = name;
3453 op->tooltip = tooltip;
3454 op->flags = flags;
3455 op->valtype = valtype;
3456 op->column_id = -1;
3457 op->parent_page = parent;
3458
3459 return op;
3460}
3461
3462/************************************************************************/
3466 static struct extviewer *extviewer_new(struct objprop *op)
3467{
3468 struct extviewer *ev;
3469 GtkWidget *hbox, *vbox, *label, *button, *scrollwin, *image;
3470 GtkWidget *view = NULL;
3471 GtkTreeSelection *sel;
3472 GtkListStore *store = NULL;
3473 GtkTextBuffer *textbuf = NULL;
3474 GType *gtypes;
3475 enum object_property_ids propid;
3476 int num_cols;
3477
3478 if (!op) {
3479 return NULL;
3480 }
3481
3482 ev = fc_calloc(1, sizeof(*ev));
3483 ev->objprop = op;
3484
3485 propid = objprop_get_id(op);
3486
3487
3488 /* Create the panel widget. */
3489
3490 switch (propid) {
3491 case OPID_TILE_SPECIALS:
3492 case OPID_TILE_ROADS:
3493 case OPID_TILE_BASES:
3494 case OPID_STARTPOS_NATIONS:
3495 case OPID_CITY_BUILDINGS:
3496 case OPID_PLAYER_INVENTIONS:
3497 case OPID_GAME_SCENARIO_AUTHORS:
3498 case OPID_GAME_SCENARIO_DESC:
3499 hbox = gtk_grid_new();
3500 gtk_grid_set_column_spacing(GTK_GRID(hbox), 4);
3501 ev->panel_widget = hbox;
3502
3503 label = gtk_label_new(NULL);
3504 gtk_widget_set_halign(label, GTK_ALIGN_START);
3505 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
3506 gtk_container_add(GTK_CONTAINER(hbox), label);
3507 ev->panel_label = label;
3508 break;
3509
3510 case OPID_PLAYER_NATION:
3511 case OPID_PLAYER_GOV:
3512 vbox = gtk_grid_new();
3513 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
3514 GTK_ORIENTATION_VERTICAL);
3515 gtk_grid_set_row_spacing(GTK_GRID(vbox), 4);
3516 ev->panel_widget = vbox;
3517
3518 label = gtk_label_new(NULL);
3519 gtk_widget_set_halign(label, GTK_ALIGN_START);
3520 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
3521 gtk_container_add(GTK_CONTAINER(vbox), label);
3522 ev->panel_label = label;
3523
3524 hbox = gtk_grid_new();
3525 gtk_grid_set_column_spacing(GTK_GRID(hbox), 4);
3526 gtk_container_add(GTK_CONTAINER(vbox), hbox);
3527
3528 image = gtk_image_new();
3529 gtk_widget_set_halign(image, GTK_ALIGN_START);
3530 gtk_widget_set_valign(image, GTK_ALIGN_CENTER);
3531 gtk_container_add(GTK_CONTAINER(hbox), image);
3532 ev->panel_image = image;
3533 break;
3534
3535 case OPID_TILE_VISION:
3536 hbox = gtk_grid_new();
3537 gtk_grid_set_column_spacing(GTK_GRID(hbox), 4);
3538 ev->panel_widget = hbox;
3539 break;
3540
3541 default:
3542 log_error("Unhandled request to create panel widget "
3543 "for property %d (%s) in extviewer_new().",
3544 propid, objprop_get_name(op));
3545 hbox = gtk_grid_new();
3546 gtk_grid_set_column_spacing(GTK_GRID(hbox), 4);
3547 ev->panel_widget = hbox;
3548 break;
3549 }
3550
3551 if (objprop_is_readonly(op)) {
3552 button = gtk_button_new_with_label(Q_("?verb:View"));
3553 } else {
3554 button = gtk_button_new_with_label(_("Edit"));
3555 }
3556 g_signal_connect(button, "clicked",
3557 G_CALLBACK(extviewer_panel_button_clicked), ev);
3558 gtk_container_add(GTK_CONTAINER(hbox), button);
3559 ev->panel_button = button;
3560
3561
3562 /* Create the data store. */
3563
3564 switch (propid) {
3565 case OPID_TILE_SPECIALS:
3566 case OPID_TILE_ROADS:
3567 case OPID_TILE_BASES:
3568 case OPID_PLAYER_INVENTIONS:
3569 store = gtk_list_store_new(3, G_TYPE_BOOLEAN, G_TYPE_INT,
3570 G_TYPE_STRING);
3571 break;
3572 case OPID_TILE_VISION:
3573 num_cols = 3 + 1 + V_COUNT;
3574 gtypes = fc_malloc(num_cols * sizeof(GType));
3575 gtypes[0] = G_TYPE_INT; /* player number */
3576 gtypes[1] = GDK_TYPE_PIXBUF; /* player flag */
3577 gtypes[2] = G_TYPE_STRING; /* player name */
3578 gtypes[3] = G_TYPE_BOOLEAN; /* tile_known */
3579 vision_layer_iterate(v) {
3580 gtypes[4 + v] = G_TYPE_BOOLEAN; /* tile_seen[v] */
3581 } vision_layer_iterate_end;
3582 store = gtk_list_store_newv(num_cols, gtypes);
3583 free(gtypes);
3584 break;
3585 case OPID_CITY_BUILDINGS:
3586 store = gtk_list_store_new(4, G_TYPE_BOOLEAN, G_TYPE_INT,
3587 G_TYPE_STRING, G_TYPE_STRING);
3588 break;
3589 case OPID_STARTPOS_NATIONS:
3590 case OPID_PLAYER_NATION:
3591 case OPID_PLAYER_GOV:
3592 store = gtk_list_store_new(4, G_TYPE_BOOLEAN, G_TYPE_INT,
3593 GDK_TYPE_PIXBUF, G_TYPE_STRING);
3594 break;
3595 case OPID_GAME_SCENARIO_AUTHORS:
3596 case OPID_GAME_SCENARIO_DESC:
3597 textbuf = gtk_text_buffer_new(NULL);
3598 break;
3599 default:
3600 log_error("Unhandled request to create data store "
3601 "for property %d (%s) in extviewer_new().",
3602 propid, objprop_get_name(op));
3603 break;
3604 }
3605
3606 ev->store = store;
3607 ev->textbuf = textbuf;
3608
3609 /* Create the view widget. */
3610
3611 vbox = gtk_grid_new();
3612 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
3613 GTK_ORIENTATION_VERTICAL);
3614 gtk_grid_set_row_spacing(GTK_GRID(vbox), 4);
3615 gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
3616 ev->view_widget = vbox;
3617
3618 label = gtk_label_new(objprop_get_name(op));
3619 gtk_widget_set_halign(label, GTK_ALIGN_START);
3620 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
3621 gtk_container_add(GTK_CONTAINER(vbox), label);
3622 ev->view_label = label;
3623
3624 if (store || textbuf) {
3625 scrollwin = gtk_scrolled_window_new(NULL, NULL);
3626 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwin),
3627 GTK_SHADOW_ETCHED_IN);
3628 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
3629 GTK_POLICY_AUTOMATIC,
3630 GTK_POLICY_AUTOMATIC);
3631 gtk_container_add(GTK_CONTAINER(vbox), scrollwin);
3632
3633 if (store) {
3634 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
3635 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE);
3636 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
3637 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
3638 } else {
3639 const bool editable = !objprop_is_readonly(op);
3640 view = gtk_text_view_new_with_buffer(textbuf);
3641 gtk_text_view_set_editable(GTK_TEXT_VIEW(view), editable);
3642 gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(view), editable);
3643 }
3644 gtk_widget_set_hexpand(view, TRUE);
3645 gtk_widget_set_vexpand(view, TRUE);
3646
3647 gtk_container_add(GTK_CONTAINER(scrollwin), view);
3648 }
3649
3650 switch (propid) {
3651
3652 case OPID_TILE_SPECIALS:
3653 case OPID_TILE_ROADS:
3654 case OPID_TILE_BASES:
3655 /* TRANS: As in "this tile special is present". */
3656 add_column(view, 0, _("Present"), G_TYPE_BOOLEAN, TRUE, FALSE,
3657 G_CALLBACK(extviewer_view_cell_toggled), ev);
3658 add_column(view, 1, _("ID"), G_TYPE_INT,
3659 FALSE, FALSE, NULL, NULL);
3660 add_column(view, 2, _("Name"), G_TYPE_STRING,
3661 FALSE, FALSE, NULL, NULL);
3662 break;
3663
3664 case OPID_TILE_VISION:
3665 add_column(view, 0, _("ID"), G_TYPE_INT,
3666 FALSE, FALSE, NULL, NULL);
3667 add_column(view, 1, _("Nation"), GDK_TYPE_PIXBUF,
3668 FALSE, FALSE, NULL, NULL);
3669 add_column(view, 2, _("Name"), G_TYPE_STRING,
3670 FALSE, FALSE, NULL, NULL);
3671 add_column(view, 3, _("Known"), G_TYPE_BOOLEAN,
3672 FALSE, FALSE, NULL, NULL);
3673 vision_layer_iterate(v) {
3674 add_column(view, 4 + v, vision_layer_get_name(v),
3675 G_TYPE_BOOLEAN, FALSE, FALSE, NULL, NULL);
3676 } vision_layer_iterate_end;
3677 break;
3678
3679 case OPID_CITY_BUILDINGS:
3680 /* TRANS: As in "this building is present". */
3681 add_column(view, 0, _("Present"), G_TYPE_BOOLEAN, TRUE, FALSE,
3682 G_CALLBACK(extviewer_view_cell_toggled), ev);
3683 add_column(view, 1, _("ID"), G_TYPE_INT,
3684 FALSE, FALSE, NULL, NULL);
3685 add_column(view, 2, _("Name"), G_TYPE_STRING,
3686 FALSE, FALSE, NULL, NULL);
3687 /* TRANS: As in "the turn when this building was built". */
3688 add_column(view, 3, _("Turn Built"), G_TYPE_STRING,
3689 FALSE, FALSE, NULL, NULL);
3690 break;
3691
3692 case OPID_STARTPOS_NATIONS:
3693 /* TRANS: As in "the player has set this nation". */
3694 add_column(view, 0, _("Set"), G_TYPE_BOOLEAN, TRUE, FALSE,
3695 G_CALLBACK(extviewer_view_cell_toggled), ev);
3696 add_column(view, 1, _("ID"), G_TYPE_INT,
3697 FALSE, FALSE, NULL, NULL);
3698 add_column(view, 2, _("Flag"), GDK_TYPE_PIXBUF,
3699 FALSE, FALSE, NULL, NULL);
3700 add_column(view, 3, _("Name"), G_TYPE_STRING,
3701 FALSE, FALSE, NULL, NULL);
3702 break;
3703
3704 case OPID_PLAYER_NATION:
3705 case OPID_PLAYER_GOV:
3706 /* TRANS: As in "the player has set this nation". */
3707 add_column(view, 0, _("Set"), G_TYPE_BOOLEAN, TRUE, TRUE,
3708 G_CALLBACK(extviewer_view_cell_toggled), ev);
3709 add_column(view, 1, _("ID"), G_TYPE_INT,
3710 FALSE, FALSE, NULL, NULL);
3711 add_column(view, 2,
3712 propid == OPID_PLAYER_GOV ? _("Icon") : _("Flag"),
3713 GDK_TYPE_PIXBUF,
3714 FALSE, FALSE, NULL, NULL);
3715 add_column(view, 3, _("Name"), G_TYPE_STRING,
3716 FALSE, FALSE, NULL, NULL);
3717 break;
3718
3719 case OPID_PLAYER_INVENTIONS:
3720 /* TRANS: As in "this invention is known". */
3721 add_column(view, 0, _("Known"), G_TYPE_BOOLEAN, TRUE, FALSE,
3722 G_CALLBACK(extviewer_view_cell_toggled), ev);
3723 add_column(view, 1, _("ID"), G_TYPE_INT,
3724 FALSE, FALSE, NULL, NULL);
3725 add_column(view, 2, _("Name"), G_TYPE_STRING,
3726 FALSE, FALSE, NULL, NULL);
3727 break;
3728
3729 case OPID_GAME_SCENARIO_AUTHORS:
3730 case OPID_GAME_SCENARIO_DESC:
3731 g_signal_connect(textbuf, "changed",
3732 G_CALLBACK(extviewer_textbuf_changed), ev);
3733 break;
3734
3735 default:
3736 log_error("Unhandled request to configure view widget "
3737 "for property %d (%s) in extviewer_new().",
3738 propid, objprop_get_name(op));
3739 break;
3740 }
3741
3742 gtk_widget_show_all(ev->panel_widget);
3743 gtk_widget_show_all(ev->view_widget);
3744
3745 return ev;
3746}
3747
3748/************************************************************************/
3751 static struct objprop *extviewer_get_objprop(struct extviewer *ev)
3752{
3753 if (!ev) {
3754 return NULL;
3755 }
3756 return ev->objprop;
3757}
3758
3759/************************************************************************/
3763 static GtkWidget *extviewer_get_panel_widget(struct extviewer *ev)
3764{
3765 if (!ev) {
3766 return NULL;
3767 }
3768 return ev->panel_widget;
3769}
3770
3771/************************************************************************/
3775 static GtkWidget *extviewer_get_view_widget(struct extviewer *ev)
3776{
3777 if (!ev) {
3778 return NULL;
3779 }
3780 return ev->view_widget;
3781}
3782
3783/************************************************************************/
3786 static void extviewer_refresh_widgets(struct extviewer *ev,
3787 struct propval *pv)
3788{
3789 struct objprop *op;
3790 enum object_property_ids propid;
3791 int id, turn_built;
3792 bool present, all;
3793 const char *name;
3794 GdkPixbuf *pixbuf;
3795 GtkListStore *store;
3796 GtkTextBuffer *textbuf;
3797 GtkTreeIter iter;
3798 gchar *buf;
3799
3800 if (!ev) {
3801 return;
3802 }
3803
3804 op = extviewer_get_objprop(ev);
3805 propid = objprop_get_id(op);
3806
3807 if (propval_equal(pv, ev->pv_cached)) {
3808 return;
3809 }
3810 propval_free(ev->pv_cached);
3811 ev->pv_cached = propval_copy(pv);
3812 store = ev->store;
3813 textbuf = ev->textbuf;
3814
3815
3816 /* NB: Remember to have -1 as the last argument to
3817 * gtk_list_store_set() and to use the correct column
3818 * number when inserting data. :) */
3819 switch (propid) {
3820
3821 case OPID_TILE_SPECIALS:
3822 gtk_list_store_clear(store);
3823 extra_type_by_cause_iterate(EC_SPECIAL, spe) {
3824 id = spe->data.special_idx;
3825 name = extra_name_translation(spe);
3826 present = BV_ISSET(pv->data.v_bv_special, id);
3827 gtk_list_store_append(store, &iter);
3828 gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name, -1);
3829 } extra_type_by_cause_iterate_end;
3830 buf = propval_as_string(pv);
3831 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
3832 g_free(buf);
3833 break;
3834
3835 case OPID_TILE_ROADS:
3836 gtk_list_store_clear(store);
3837 extra_type_by_cause_iterate(EC_ROAD, pextra) {
3838 struct road_type *proad = extra_road_get(pextra);
3839
3840 id = road_number(proad);
3841 name = extra_name_translation(pextra);
3842 present = BV_ISSET(pv->data.v_bv_roads, id);
3843 gtk_list_store_append(store, &iter);
3844 gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name, -1);
3845 } extra_type_by_cause_iterate_end;
3846 buf = propval_as_string(pv);
3847 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
3848 g_free(buf);
3849 break;
3850
3851 case OPID_TILE_BASES:
3852 gtk_list_store_clear(store);
3853 extra_type_by_cause_iterate(EC_BASE, pextra) {
3854 struct base_type *pbase = extra_base_get(pextra);
3855
3856 id = base_number(pbase);
3857 name = extra_name_translation(pextra);
3858 present = BV_ISSET(pv->data.v_bv_bases, id);
3859 gtk_list_store_append(store, &iter);
3860 gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name, -1);
3861 } extra_type_by_cause_iterate_end;
3862 buf = propval_as_string(pv);
3863 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
3864 g_free(buf);
3865 break;
3866
3867 case OPID_TILE_VISION:
3868 gtk_list_store_clear(store);
3869 player_slots_iterate(pslot) {
3870 id = player_slot_index(pslot);
3871 if (player_slot_is_used(pslot)) {
3872 struct player *pplayer = player_slot_get_player(pslot);
3873 name = player_name(pplayer);
3874 pixbuf = get_flag(pplayer->nation);
3875 } else {
3876 name = "";
3877 pixbuf = NULL;
3878 }
3879 gtk_list_store_append(store, &iter);
3880 gtk_list_store_set(store, &iter, 0, id, 2, name, -1);
3881 if (pixbuf) {
3882 gtk_list_store_set(store, &iter, 1, pixbuf, -1);
3883 g_object_unref(pixbuf);
3884 pixbuf = NULL;
3885 }
3886 present = BV_ISSET(pv->data.v_tile_vision->tile_known, id);
3887 gtk_list_store_set(store, &iter, 3, present, -1);
3888 vision_layer_iterate(v) {
3889 present = BV_ISSET(pv->data.v_tile_vision->tile_seen[v], id);
3890 gtk_list_store_set(store, &iter, 4 + v, present, -1);
3891 } vision_layer_iterate_end;
3892 } player_slots_iterate_end;
3893 break;
3894
3895 case OPID_STARTPOS_NATIONS:
3896 gtk_list_store_clear(store);
3897 gtk_list_store_append(store, &iter);
3898 all = (0 == nation_hash_size(pv->data.v_nation_hash));
3899 gtk_list_store_set(store, &iter, 0, all, 1, -1, 3,
3900 _("All nations"), -1);
3901 nations_iterate(pnation) {
3902 if (client_nation_is_in_current_set(pnation)
3903 && is_nation_playable(pnation)) {
3904 present = (!all && nation_hash_lookup(pv->data.v_nation_hash,
3905 pnation, NULL));
3906 id = nation_number(pnation);
3907 pixbuf = get_flag(pnation);
3908 name = nation_adjective_translation(pnation);
3909 gtk_list_store_append(store, &iter);
3910 gtk_list_store_set(store, &iter, 0, present, 1, id,
3911 2, pixbuf, 3, name, -1);
3912 if (pixbuf) {
3913 g_object_unref(pixbuf);
3914 }
3915 }
3916 } nations_iterate_end;
3917 buf = propval_as_string(pv);
3918 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
3919 g_free(buf);
3920 break;
3921
3922 case OPID_CITY_BUILDINGS:
3923 gtk_list_store_clear(store);
3924 improvement_iterate(pimprove) {
3925 if (is_special_improvement(pimprove)) {
3926 continue;
3927 }
3928 id = improvement_index(pimprove);
3929 name = improvement_name_translation(pimprove);
3930 turn_built = pv->data.v_built[id].turn;
3931 present = turn_built >= 0;
3932 buf = built_status_to_string(&pv->data.v_built[id]);
3933 gtk_list_store_append(store, &iter);
3934 gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name,
3935 3, buf, -1);
3936 g_free(buf);
3937 } improvement_iterate_end;
3938 buf = propval_as_string(pv);
3939 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
3940 g_free(buf);
3941 break;
3942
3943 case OPID_PLAYER_NATION:
3944 {
3945 enum barbarian_type barbarian_type =
3946 nation_barbarian_type(pv->data.v_nation);
3947
3948 gtk_list_store_clear(store);
3949 nations_iterate(pnation) {
3950 if (client_nation_is_in_current_set(pnation)
3951 && nation_barbarian_type(pnation) == barbarian_type
3952 && (barbarian_type != NOT_A_BARBARIAN
3953 || is_nation_playable(pnation))) {
3954 present = (pnation == pv->data.v_nation);
3955 id = nation_index(pnation);
3956 pixbuf = get_flag(pnation);
3957 name = nation_adjective_translation(pnation);
3958 gtk_list_store_append(store, &iter);
3959 gtk_list_store_set(store, &iter, 0, present, 1, id,
3960 2, pixbuf, 3, name, -1);
3961 if (pixbuf) {
3962 g_object_unref(pixbuf);
3963 }
3964 }
3965 } nations_iterate_end;
3966 gtk_label_set_text(GTK_LABEL(ev->panel_label),
3967 nation_adjective_translation(pv->data.v_nation));
3968 pixbuf = get_flag(pv->data.v_nation);
3969 gtk_image_set_from_pixbuf(GTK_IMAGE(ev->panel_image), pixbuf);
3970 if (pixbuf) {
3971 g_object_unref(pixbuf);
3972 }
3973 }
3974 break;
3975
3976 case OPID_PLAYER_GOV:
3977 {
3978 gtk_list_store_clear(store);
3979 governments_iterate(pgov) {
3980 present = (pgov == pv->data.v_gov);
3981 id = government_index(pgov);
3982 pixbuf = sprite_get_pixbuf(get_government_sprite(tileset, pgov));
3983 name = government_name_translation(pgov);
3984 gtk_list_store_append(store, &iter);
3985 gtk_list_store_set(store, &iter, 0, present, 1, id,
3986 2, pixbuf, 3, name, -1);
3987 if (pixbuf) {
3988 g_object_unref(pixbuf);
3989 }
3990 } governments_iterate_end;
3991 gtk_label_set_text(GTK_LABEL(ev->panel_label),
3992 government_name_translation(pv->data.v_gov));
3993 pixbuf = sprite_get_pixbuf(get_government_sprite(tileset, pv->data.v_gov));
3994 gtk_image_set_from_pixbuf(GTK_IMAGE(ev->panel_image), pixbuf);
3995 if (pixbuf) {
3996 g_object_unref(pixbuf);
3997 }
3998 }
3999 break;
4000
4001 case OPID_PLAYER_INVENTIONS:
4002 gtk_list_store_clear(store);
4003 advance_iterate(A_FIRST, padvance) {
4004 id = advance_index(padvance);
4005 present = BV_ISSET(pv->data.v_bv_inventions, id);
4006 name = advance_name_translation(padvance);
4007 gtk_list_store_append(store, &iter);
4008 gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name, -1);
4009 } advance_iterate_end;
4010 buf = propval_as_string(pv);
4011 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4012 g_free(buf);
4013 break;
4014
4015 case OPID_GAME_SCENARIO_AUTHORS:
4016 case OPID_GAME_SCENARIO_DESC:
4017 disable_gobject_callback(G_OBJECT(ev->textbuf),
4018 G_CALLBACK(extviewer_textbuf_changed));
4019 {
4020 GtkTextIter start, end;
4021 char *oldtext;
4022
4023 /* Don't re-set content if unchanged, to avoid moving cursor */
4024 gtk_text_buffer_get_bounds(textbuf, &start, &end);
4025 oldtext = gtk_text_buffer_get_text(textbuf, &start, &end, TRUE);
4026 if (strcmp(oldtext, pv->data.v_const_string) != 0) {
4027 gtk_text_buffer_set_text(textbuf, pv->data.v_const_string, -1);
4028 }
4029 }
4030 enable_gobject_callback(G_OBJECT(ev->textbuf),
4031 G_CALLBACK(extviewer_textbuf_changed));
4032 gtk_widget_set_sensitive(ev->view_widget, TRUE);
4033 buf = propval_as_string(pv);
4034 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4035 g_free(buf);
4036 break;
4037
4038 default:
4039 log_error("Unhandled request to refresh widgets "
4040 "extviewer_refresh_widgets() for objprop id=%d "
4041 "name \"%s\".", propid, objprop_get_name(op));
4042 break;
4043 }
4044}
4045
4046/************************************************************************/
4049 static void extviewer_clear_widgets(struct extviewer *ev)
4050{
4051 struct objprop *op;
4052 enum object_property_ids propid;
4053
4054 if (!ev) {
4055 return;
4056 }
4057
4058 op = extviewer_get_objprop(ev);
4059 propid = objprop_get_id(op);
4060
4061 propval_free(ev->pv_cached);
4062 ev->pv_cached = NULL;
4063
4064 if (ev->panel_label != NULL) {
4065 gtk_label_set_text(GTK_LABEL(ev->panel_label), NULL);
4066 }
4067
4068 switch (propid) {
4069 case OPID_TILE_SPECIALS:
4070 case OPID_TILE_ROADS:
4071 case OPID_TILE_BASES:
4072 case OPID_TILE_VISION:
4073 case OPID_STARTPOS_NATIONS:
4074 case OPID_CITY_BUILDINGS:
4075 case OPID_PLAYER_INVENTIONS:
4076 gtk_list_store_clear(ev->store);
4077 break;
4078 case OPID_PLAYER_NATION:
4079 case OPID_PLAYER_GOV:
4080 gtk_list_store_clear(ev->store);
4081 gtk_image_set_from_pixbuf(GTK_IMAGE(ev->panel_image), NULL);
4082 break;
4083 case OPID_GAME_SCENARIO_AUTHORS:
4084 case OPID_GAME_SCENARIO_DESC:
4085 disable_gobject_callback(G_OBJECT(ev->textbuf),
4086 G_CALLBACK(extviewer_textbuf_changed));
4087 gtk_text_buffer_set_text(ev->textbuf, "", -1);
4088 enable_gobject_callback(G_OBJECT(ev->textbuf),
4089 G_CALLBACK(extviewer_textbuf_changed));
4090 gtk_widget_set_sensitive(ev->view_widget, FALSE);
4091 break;
4092 default:
4093 log_error("Unhandled request to clear widgets "
4094 "in extviewer_clear_widgets() for objprop id=%d "
4095 "name \"%s\".", propid, objprop_get_name(op));
4096 break;
4097 }
4098}
4099
4100/************************************************************************/
4104 static void extviewer_panel_button_clicked(GtkButton *button,
4105 gpointer userdata)
4106{
4107 struct extviewer *ev;
4108 struct property_page *pp;
4109 struct objprop *op;
4110
4111 ev = userdata;
4112 if (!ev) {
4113 return;
4114 }
4115
4116 op = extviewer_get_objprop(ev);
4117 pp = objprop_get_property_page(op);
4118 property_page_show_extviewer(pp, ev);
4119}
4120
4121/************************************************************************/
4124 static void extviewer_view_cell_toggled(GtkCellRendererToggle *cell,
4125 gchar *path,
4126 gpointer userdata)
4127{
4128 struct extviewer *ev;
4129 struct objprop *op;
4130 struct property_page *pp;
4131 enum object_property_ids propid;
4132 GtkTreeModel *model;
4133 GtkTreeIter iter;
4134 int id, old_id, turn_built;
4135 struct propval *pv;
4136 bool active, present;
4137 gchar *buf;
4138 GdkPixbuf *pixbuf = NULL;
4139
4140 ev = userdata;
4141 if (!ev) {
4142 return;
4143 }
4144
4145 pv = ev->pv_cached;
4146 if (!pv) {
4147 return;
4148 }
4149
4150 op = extviewer_get_objprop(ev);
4151 propid = objprop_get_id(op);
4152 active = gtk_cell_renderer_toggle_get_active(cell);
4153 pp = objprop_get_property_page(op);
4154
4155 model = GTK_TREE_MODEL(ev->store);
4156 if (!gtk_tree_model_get_iter_from_string(model, &iter, path)) {
4157 return;
4158 }
4159 present = !active;
4160
4161
4162 switch (propid) {
4163
4164 case OPID_TILE_SPECIALS:
4165 gtk_tree_model_get(model, &iter, 1, &id, -1);
4166 if (id < 0 || id >= extra_type_list_size(extra_type_list_by_cause(EC_SPECIAL))) {
4167 return;
4168 }
4169 if (present) {
4170 BV_SET(pv->data.v_bv_special, id);
4171 } else {
4172 BV_CLR(pv->data.v_bv_special, id);
4173 }
4174 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4175 buf = propval_as_string(pv);
4176 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4177 g_free(buf);
4178 break;
4179
4180 case OPID_TILE_ROADS:
4181 gtk_tree_model_get(model, &iter, 1, &id, -1);
4182 if (!(0 <= id && id < road_count())) {
4183 return;
4184 }
4185 if (present) {
4186 BV_SET(pv->data.v_bv_roads, id);
4187 } else {
4188 BV_CLR(pv->data.v_bv_roads, id);
4189 }
4190 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4191 buf = propval_as_string(pv);
4192 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4193 g_free(buf);
4194 break;
4195
4196 case OPID_TILE_BASES:
4197 gtk_tree_model_get(model, &iter, 1, &id, -1);
4198 if (!(0 <= id && id < base_count())) {
4199 return;
4200 }
4201 if (present) {
4202 BV_SET(pv->data.v_bv_bases, id);
4203 } else {
4204 BV_CLR(pv->data.v_bv_bases, id);
4205 }
4206 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4207 buf = propval_as_string(pv);
4208 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4209 g_free(buf);
4210 break;
4211
4212 case OPID_STARTPOS_NATIONS:
4213 gtk_tree_model_get(model, &iter, 1, &id, -1);
4214 if (-1 > id && id >= nation_count()) {
4215 return;
4216 }
4217
4218 if (-1 == id) {
4219 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4220 gtk_tree_model_get_iter_first(model, &iter);
4221 if (present) {
4222 while (gtk_tree_model_iter_next(model, &iter)) {
4223 gtk_list_store_set(ev->store, &iter, 0, FALSE, -1);
4224 }
4225 nation_hash_clear(pv->data.v_nation_hash);
4226 } else {
4227 const struct nation_type *pnation;
4228 int id2;
4229
4230 gtk_tree_model_iter_next(model, &iter);
4231 gtk_tree_model_get(model, &iter, 0, &id2, -1);
4232 gtk_list_store_set(ev->store, &iter, 0, TRUE, -1);
4233 pnation = nation_by_number(id2);
4234 nation_hash_insert(pv->data.v_nation_hash, pnation, NULL);
4235 }
4236 } else {
4237 const struct nation_type *pnation;
4238 bool all;
4239
4240 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4241 pnation = nation_by_number(id);
4242 if (present) {
4243 nation_hash_insert(pv->data.v_nation_hash, pnation, NULL);
4244 } else {
4245 nation_hash_remove(pv->data.v_nation_hash, pnation);
4246 }
4247 gtk_tree_model_get_iter_first(model, &iter);
4248 all = (0 == nation_hash_size(pv->data.v_nation_hash));
4249 gtk_list_store_set(ev->store, &iter, 0, all, -1);
4250 }
4251 buf = propval_as_string(pv);
4252 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4253 g_free(buf);
4254 break;
4255
4256 case OPID_CITY_BUILDINGS:
4257 gtk_tree_model_get(model, &iter, 1, &id, -1);
4258 if (!(0 <= id && id < B_LAST)) {
4259 return;
4260 }
4261 turn_built = present ? game.info.turn : I_NEVER;
4262 pv->data.v_built[id].turn = turn_built;
4263 buf = built_status_to_string(&pv->data.v_built[id]);
4264 gtk_list_store_set(ev->store, &iter, 0, present, 3, buf, -1);
4265 g_free(buf);
4266 buf = propval_as_string(pv);
4267 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4268 g_free(buf);
4269 break;
4270
4271 case OPID_PLAYER_NATION:
4272 gtk_tree_model_get(model, &iter, 1, &id, -1);
4273 if (!(0 <= id && id < nation_count()) || !present) {
4274 return;
4275 }
4276 old_id = nation_index(pv->data.v_nation);
4277 pv->data.v_nation = nation_by_number(id);
4278 gtk_list_store_set(ev->store, &iter, 0, TRUE, -1);
4279 gtk_tree_model_iter_nth_child(model, &iter, NULL, old_id);
4280 gtk_list_store_set(ev->store, &iter, 0, FALSE, -1);
4281 gtk_label_set_text(GTK_LABEL(ev->panel_label),
4282 nation_adjective_translation(pv->data.v_nation));
4283 pixbuf = get_flag(pv->data.v_nation);
4284 gtk_image_set_from_pixbuf(GTK_IMAGE(ev->panel_image), pixbuf);
4285 if (pixbuf) {
4286 g_object_unref(pixbuf);
4287 }
4288 break;
4289
4290 case OPID_PLAYER_GOV:
4291 gtk_tree_model_get(model, &iter, 1, &id, -1);
4292 if (!(0 <= id && id < government_count()) || !present) {
4293 return;
4294 }
4295 old_id = government_index(pv->data.v_gov);
4296 pv->data.v_gov = government_by_number(id);
4297 gtk_list_store_set(ev->store, &iter, 0, TRUE, -1);
4298 gtk_tree_model_iter_nth_child(model, &iter, NULL, old_id);
4299 gtk_list_store_set(ev->store, &iter, 0, FALSE, -1);
4300 gtk_label_set_text(GTK_LABEL(ev->panel_label),
4301 government_name_translation(pv->data.v_gov));
4302 pixbuf = sprite_get_pixbuf(get_government_sprite(tileset, pv->data.v_gov));
4303 gtk_image_set_from_pixbuf(GTK_IMAGE(ev->panel_image), pixbuf);
4304 if (pixbuf) {
4305 g_object_unref(pixbuf);
4306 }
4307 break;
4308
4309 case OPID_PLAYER_INVENTIONS:
4310 gtk_tree_model_get(model, &iter, 1, &id, -1);
4311 if (!(A_FIRST <= id && id < advance_count())) {
4312 return;
4313 }
4314 if (present) {
4315 BV_SET(pv->data.v_bv_inventions, id);
4316 } else {
4317 BV_CLR(pv->data.v_bv_inventions, id);
4318 }
4319 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4320 buf = propval_as_string(pv);
4321 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4322 g_free(buf);
4323 break;
4324
4325 default:
4326 log_error("Unhandled widget toggled signal in "
4327 "extviewer_view_cell_toggled() for objprop id=%d "
4328 "name \"%s\".", propid, objprop_get_name(op));
4329 return;
4330 break;
4331 }
4332
4333 property_page_change_value(pp, op, pv);
4334}
4335
4336/************************************************************************/
4339 static void extviewer_textbuf_changed(GtkTextBuffer *textbuf,
4340 gpointer userdata)
4341{
4342 struct extviewer *ev;
4343 struct objprop *op;
4344 struct property_page *pp;
4345 enum object_property_ids propid;
4346 struct propval value = {{0,}, VALTYPE_STRING, FALSE}, *pv;
4347 GtkTextIter start, end;
4348 char *text;
4349 gchar *buf;
4350
4351 ev = userdata;
4352 if (!ev) {
4353 return;
4354 }
4355
4356 op = extviewer_get_objprop(ev);
4357 propid = objprop_get_id(op);
4358 pp = objprop_get_property_page(op);
4359
4360 gtk_text_buffer_get_start_iter(textbuf, &start);
4361 gtk_text_buffer_get_end_iter(textbuf, &end);
4362 text = gtk_text_buffer_get_text(textbuf, &start, &end, FALSE);
4363 value.data.v_const_string = text;
4364 pv = &value;
4365
4366 switch (propid) {
4367 case OPID_GAME_SCENARIO_AUTHORS:
4368 case OPID_GAME_SCENARIO_DESC:
4369 buf = propval_as_string(pv);
4370 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4371 g_free(buf);
4372 break;
4373 default:
4374 log_error("Unhandled widget modified signal in "
4375 "extviewer_textbuf_changed() for objprop id=%d "
4376 "name \"%s\".", propid, objprop_get_name(op));
4377 return;
4378 break;
4379 }
4380
4381 property_page_change_value(pp, op, pv);
4382 g_free(text);
4383}
4384
4385/************************************************************************/
4388 static void property_page_setup_objprops(struct property_page *pp)
4389{
4390#define ADDPROP(ARG_id, ARG_name, ARG_tooltip, ARG_flags, ARG_valtype) do { \
4391 struct objprop *MY_op = objprop_new(ARG_id, ARG_name, ARG_tooltip, \
4392 ARG_flags, ARG_valtype, pp); \
4393 objprop_hash_insert(pp->objprop_table, MY_op->id, MY_op); \
4394} while (FALSE)
4395
4396 switch (property_page_get_objtype(pp)) {
4397 case OBJTYPE_TILE:
4398 ADDPROP(OPID_TILE_IMAGE, _("Image"), NULL,
4399 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_PIXBUF);
4400 ADDPROP(OPID_TILE_TERRAIN, _("Terrain"), NULL,
4401 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_STRING);
4402 ADDPROP(OPID_TILE_RESOURCE, _("Resource"), NULL,
4403 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_STRING);
4404 ADDPROP(OPID_TILE_INDEX, _("Index"), NULL,
4405 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_INT);
4406 ADDPROP(OPID_TILE_X, Q_("?coordinate:X"), NULL,
4407 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_INT);
4408 ADDPROP(OPID_TILE_Y, Q_("?coordinate:Y"), NULL,
4409 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_INT);
4410 /* TRANS: The coordinate X in native coordinates.
4411 * The freeciv coordinate system is described in doc/HACKING. */
4412 ADDPROP(OPID_TILE_NAT_X, _("NAT X"), NULL,
4413 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_INT);
4414 /* TRANS: The coordinate Y in native coordinates.
4415 * The freeciv coordinate system is described in doc/HACKING. */
4416 ADDPROP(OPID_TILE_NAT_Y, _("NAT Y"), NULL,
4417 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_INT);
4418 ADDPROP(OPID_TILE_CONTINENT, _("Continent"), NULL,
4419 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_INT);
4420 ADDPROP(OPID_TILE_XY, Q_("?coordinates:X,Y"), NULL,
4421 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_STRING);
4422 ADDPROP(OPID_TILE_SPECIALS, _("Specials"), NULL,
4423 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE,
4424 VALTYPE_BV_SPECIAL);
4425 ADDPROP(OPID_TILE_ROADS, _("Roads"), NULL,
4426 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE,
4427 VALTYPE_BV_ROADS);
4428 ADDPROP(OPID_TILE_BASES, _("Bases"), NULL,
4429 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE,
4430 VALTYPE_BV_BASES);
4431#ifdef FREECIV_DEBUG
4432 ADDPROP(OPID_TILE_ADDRESS, _("Address"), NULL,
4433 OPF_HAS_WIDGET, VALTYPE_STRING);
4434#endif /* FREECIV_DEBUG */
4435#if 0
4436 /* Disabled entirely for now as server is not sending other
4437 * players' vision information anyway. */
4438 ADDPROP(OPID_TILE_VISION, _("Vision"), NULL,
4439 OPF_HAS_WIDGET, VALTYPE_TILE_VISION_DATA);
4440#endif
4441 /* TRANS: Tile property "Label" label in editor */
4442 ADDPROP(OPID_TILE_LABEL, Q_("?property:Label"), NULL,
4443 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_STRING);
4444 return;
4445
4446 case OBJTYPE_STARTPOS:
4447 ADDPROP(OPID_STARTPOS_IMAGE, _("Image"), NULL,
4448 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_PIXBUF);
4449 ADDPROP(OPID_STARTPOS_XY, Q_("?coordinates:X,Y"), NULL,
4450 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_STRING);
4451 ADDPROP(OPID_STARTPOS_EXCLUDE, _("Exclude Nations"), NULL,
4452 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_BOOL);
4453 ADDPROP(OPID_STARTPOS_NATIONS, _("Nations"), NULL,
4454 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE,
4455 VALTYPE_NATION_HASH);
4456 return;
4457
4458 case OBJTYPE_UNIT:
4459 ADDPROP(OPID_UNIT_IMAGE, _("Image"), NULL,
4460 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_PIXBUF);
4461#ifdef FREECIV_DEBUG
4462 ADDPROP(OPID_UNIT_ADDRESS, _("Address"), NULL,
4463 OPF_HAS_WIDGET, VALTYPE_STRING);
4464#endif /* FREECIV_DEBUG */
4465 ADDPROP(OPID_UNIT_TYPE, _("Type"), NULL,
4466 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_STRING);
4467 ADDPROP(OPID_UNIT_ID, _("ID"), NULL,
4468 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_INT);
4469 ADDPROP(OPID_UNIT_XY, Q_("?coordinates:X,Y"), NULL,
4470 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_STRING);
4471 ADDPROP(OPID_UNIT_MOVES_LEFT, _("Moves Left"), NULL,
4472 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_INT);
4473 ADDPROP(OPID_UNIT_FUEL, _("Fuel"), NULL,
4474 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_INT);
4475 ADDPROP(OPID_UNIT_MOVED, _("Moved"), NULL,
4476 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_BOOL);
4477 ADDPROP(OPID_UNIT_DONE_MOVING, _("Done Moving"), NULL,
4478 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_BOOL);
4479 /* TRANS: HP = Hit Points of a unit. */
4480 ADDPROP(OPID_UNIT_HP, _("HP"), NULL,
4481 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_INT);
4482 ADDPROP(OPID_UNIT_VETERAN, _("Veteran"), NULL,
4483 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_INT);
4484 ADDPROP(OPID_UNIT_STAY, _("Stay put"), NULL,
4485 OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_BOOL);
4486 return;
4487
4488 case OBJTYPE_CITY:
4489 ADDPROP(OPID_CITY_IMAGE, _("Image"), NULL,
4490 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_PIXBUF);
4491 ADDPROP(OPID_CITY_NAME, _("Name"), NULL,
4492 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_STRING);
4493#ifdef FREECIV_DEBUG
4494 ADDPROP(OPID_CITY_ADDRESS, _("Address"), NULL,
4495 OPF_HAS_WIDGET, VALTYPE_STRING);
4496#endif /* FREECIV_DEBUG */
4497 ADDPROP(OPID_CITY_ID, _("ID"), NULL,
4498 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_INT);
4499 ADDPROP(OPID_CITY_XY, Q_("?coordinates:X,Y"), NULL,
4500 OPF_IN_LISTVIEW | OPF_HAS_WIDGET, VALTYPE_STRING);
4501 ADDPROP(OPID_CITY_SIZE, _("Size"), NULL,
4502 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_INT);
4503 ADDPROP(OPID_CITY_HISTORY, _("History"), NULL,
4504 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_INT);
4505 ADDPROP(OPID_CITY_BUILDINGS, _("Buildings"), NULL,
4506 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE,
4507 VALTYPE_BUILT_ARRAY);
4508 ADDPROP(OPID_CITY_FOOD_STOCK, _("Food Stock"), NULL,
4509 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_INT);
4510 ADDPROP(OPID_CITY_SHIELD_STOCK, _("Shield Stock"), NULL,
4511 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_INT);
4512 return;
4513
4514 case OBJTYPE_PLAYER:
4515 ADDPROP(OPID_PLAYER_NAME, _("Name"), NULL,
4516 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE,
4517 VALTYPE_STRING);
4518#ifdef FREECIV_DEBUG
4519 ADDPROP(OPID_PLAYER_ADDRESS, _("Address"), NULL,
4520 OPF_HAS_WIDGET, VALTYPE_STRING);
4521#endif /* FREECIV_DEBUG */
4522 ADDPROP(OPID_PLAYER_NATION, _("Nation"), NULL,
4523 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE,
4524 VALTYPE_NATION);
4525 ADDPROP(OPID_PLAYER_GOV, _("Government"), NULL,
4526 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_GOV);
4527 ADDPROP(OPID_PLAYER_AGE, _("Age"), NULL,
4528 OPF_HAS_WIDGET, VALTYPE_INT);
4529 ADDPROP(OPID_PLAYER_INVENTIONS, _("Inventions"), NULL,
4530 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE,
4531 VALTYPE_INVENTIONS_ARRAY);
4532 ADDPROP(OPID_PLAYER_SCENARIO_RESERVED, _("Reserved"), NULL,
4533 OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_BOOL);
4534 ADDPROP(OPID_PLAYER_SCIENCE, _("Science"), NULL,
4535 OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_INT);
4536 ADDPROP(OPID_PLAYER_GOLD, _("Gold"), NULL,
4537 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE,
4538 VALTYPE_INT);
4539 return;
4540
4541 case OBJTYPE_GAME:
4542 ADDPROP(OPID_GAME_SCENARIO, _("Scenario"), NULL,
4543 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE,
4544 VALTYPE_BOOL);
4545 ADDPROP(OPID_GAME_SCENARIO_NAME, _("Scenario Name"), NULL,
4546 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE,
4547 VALTYPE_STRING);
4548 ADDPROP(OPID_GAME_SCENARIO_AUTHORS,
4549 _("Scenario Authors"), NULL,
4550 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE,
4551 VALTYPE_STRING);
4552 ADDPROP(OPID_GAME_SCENARIO_DESC,
4553 _("Scenario Description"), NULL,
4554 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE,
4555 VALTYPE_STRING);
4556 ADDPROP(OPID_GAME_SCENARIO_RANDSTATE,
4557 _("Save Random Number State"), NULL,
4558 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_BOOL);
4559 ADDPROP(OPID_GAME_SCENARIO_PLAYERS,
4560 _("Save Players"), NULL,
4561 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_BOOL);
4562 ADDPROP(OPID_GAME_STARTPOS_NATIONS,
4563 _("Nation Start Positions"), NULL,
4564 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_BOOL);
4565 ADDPROP(OPID_GAME_PREVENT_CITIES,
4566 _("Prevent New Cities"), NULL,
4567 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_BOOL);
4568 ADDPROP(OPID_GAME_LAKE_FLOODING,
4569 _("Saltwater Flooding Lakes"), NULL,
4570 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_BOOL);
4571 ADDPROP(OPID_GAME_RULESET_LOCKED,
4572 _("Lock to current Ruleset"), NULL,
4573 OPF_IN_LISTVIEW | OPF_HAS_WIDGET | OPF_EDITABLE, VALTYPE_BOOL);
4574 return;
4575
4576 case NUM_OBJTYPES:
4577 break;
4578 }
4579
4580 log_error("%s(): Unhandled page object type %s (nb %d).", __FUNCTION__,
4581 objtype_get_name(property_page_get_objtype(pp)),
4582 property_page_get_objtype(pp));
4583#undef ADDPROP
4584}
4585
4586/************************************************************************/
4589 static void property_page_selection_changed(GtkTreeSelection *sel,
4590 gpointer userdata)
4591{
4592 struct property_page *pp;
4593 struct objbind *ob = NULL;
4594
4595 pp = userdata;
4596 if (!pp) {
4597 return;
4598 }
4599
4600 if (gtk_tree_selection_count_selected_rows(sel) < 1) {
4601 property_page_set_focused_objbind(pp, NULL);
4602 }
4603
4604 ob = property_page_get_focused_objbind(pp);
4605 property_page_objprop_iterate(pp, op) {
4606 objprop_refresh_widget(op, ob);
4607 } property_page_objprop_iterate_end;
4608}
4609
4610/************************************************************************/
4614 static gboolean property_page_selection_func(GtkTreeSelection *sel,
4615 GtkTreeModel *model,
4616 GtkTreePath *sel_path,
4617 gboolean currently_selected,
4618 gpointer data)
4619{
4620 struct property_page *pp;
4621 struct objbind *ob = NULL, *old_ob;
4622 GtkTreeIter iter;
4623
4624 pp = data;
4625 if (!pp || !sel_path) {
4626 return TRUE;
4627 }
4628
4629 if (!gtk_tree_model_get_iter(model, &iter, sel_path)) {
4630 return TRUE;
4631 }
4632
4633 old_ob = property_page_get_focused_objbind(pp);
4634 gtk_tree_model_get(model, &iter, 0, &ob, -1);
4635 if (currently_selected) {
4636 if (ob == old_ob) {
4637 GList *rows, *p;
4638 GtkTreePath *path;
4639 struct objbind *new_ob = NULL;
4640
4641 rows = gtk_tree_selection_get_selected_rows(sel, NULL);
4642 for (p = rows; p != NULL; p = p->next) {
4643 path = p->data;
4644 if (gtk_tree_model_get_iter(model, &iter, path)) {
4645 struct objbind *test_ob = NULL;
4646 gtk_tree_model_get(model, &iter, 0, &test_ob, -1);
4647 if (test_ob == ob) {
4648 continue;
4649 }
4650 new_ob = test_ob;
4651 break;
4652 }
4653 }
4654 g_list_foreach(rows, (GFunc) gtk_tree_path_free, NULL);
4655 g_list_free(rows);
4656
4657 property_page_set_focused_objbind(pp, new_ob);
4658 }
4659 } else {
4660 property_page_set_focused_objbind(pp, ob);
4661 }
4662
4663 return TRUE;
4664}
4665
4666/************************************************************************/
4669 static void property_page_quick_find_entry_changed(GtkWidget *entry,
4670 gpointer userdata)
4671{
4672 struct property_page *pp;
4673 const gchar *text;
4674 GtkWidget *w;
4675 GtkTreeViewColumn *col;
4676 struct property_filter *pf;
4677 bool matched;
4678
4679 pp = userdata;
4680 text = gtk_entry_get_text(GTK_ENTRY(entry));
4681 pf = property_filter_new(text);
4682
4683 property_page_objprop_iterate(pp, op) {
4684 if (!objprop_has_widget(op)
4685 && !objprop_show_in_listview(op)) {
4686 continue;
4687 }
4688 matched = property_filter_match(pf, op);
4689 w = objprop_get_widget(op);
4690 if (objprop_has_widget(op) && w != NULL) {
4691 if (matched) {
4692 gtk_widget_show(w);
4693 } else {
4694 gtk_widget_hide(w);
4695 }
4696 }
4697 col = objprop_get_treeview_column(op);
4698 if (objprop_show_in_listview(op) && col != NULL) {
4699 gtk_tree_view_column_set_visible(col, matched);
4700 }
4701 } property_page_objprop_iterate_end;
4702
4703 property_filter_free(pf);
4704}
4705
4706/************************************************************************/
4710static struct property_page *
4711property_page_new(enum editor_object_type objtype,
4712 struct property_editor *pe)
4713{
4714 struct property_page *pp;
4715 GtkWidget *vbox, *vbox2, *hbox, *hbox2, *paned, *frame, *w;
4716 GtkWidget *scrollwin, *view, *label, *entry, *notebook;
4717 GtkWidget *button, *hsep, *image;
4718 GtkTreeSelection *sel;
4719 GtkCellRenderer *cell;
4720 GtkTreeViewColumn *col;
4721 GtkSizeGroup *sizegroup;
4722 int num_columns = 0;
4723 GType *gtype_array;
4724 int col_id = 1;
4725 const char *attr_type_str, *name, *tooltip;
4726 gchar *title;
4727
4728 if (!(objtype < NUM_OBJTYPES)) {
4729 return NULL;
4730 }
4731
4732 pp = fc_calloc(1, sizeof(struct property_page));
4733 pp->objtype = objtype;
4734 pp->pe_parent = pe;
4735
4736 sizegroup = gtk_size_group_new(GTK_SIZE_GROUP_BOTH);
4737
4738 pp->objprop_table = objprop_hash_new();
4739 property_page_setup_objprops(pp);
4740
4741 pp->objbind_table = objbind_hash_new();
4742
4743 pp->tag_table = stored_tag_hash_new();
4744
4745 property_page_objprop_iterate(pp, op) {
4746 if (objprop_show_in_listview(op)) {
4747 num_columns++;
4748 }
4749 } property_page_objprop_iterate_end;
4750
4751 /* Column zero in the store holds an objbind
4752 * pointer and is never displayed. */
4753 num_columns++;
4754 gtype_array = fc_malloc(num_columns * sizeof(GType));
4755 gtype_array[0] = G_TYPE_POINTER;
4756
4757 property_page_objprop_iterate(pp, op) {
4758 if (objprop_show_in_listview(op)) {
4759 gtype_array[col_id] = objprop_get_gtype(op);
4760 objprop_set_column_id(op, col_id);
4761 col_id++;
4762 }
4763 } property_page_objprop_iterate_end;
4764
4765 pp->object_store = gtk_list_store_newv(num_columns, gtype_array);
4766 free(gtype_array);
4767
4768 paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
4769 gtk_paned_set_position(GTK_PANED(paned), 256);
4770 pp->widget = paned;
4771
4772 /* Left side object list view. */
4773
4774 vbox = gtk_grid_new();
4775 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
4776 GTK_ORIENTATION_VERTICAL);
4777 gtk_grid_set_row_spacing(GTK_GRID(vbox), 4);
4778 gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
4779 gtk_paned_pack1(GTK_PANED(paned), vbox, TRUE, TRUE);
4780
4781 scrollwin = gtk_scrolled_window_new(NULL, NULL);
4782 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwin),
4783 GTK_SHADOW_ETCHED_IN);
4784 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
4785 GTK_POLICY_AUTOMATIC,
4786 GTK_POLICY_AUTOMATIC);
4787 gtk_container_add(GTK_CONTAINER(vbox), scrollwin);
4788
4789 view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(pp->object_store));
4790 gtk_widget_set_hexpand(view, TRUE);
4791 gtk_widget_set_vexpand(view, TRUE);
4792 gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(view), TRUE);
4793
4794 property_page_objprop_iterate(pp, op) {
4795 if (!objprop_show_in_listview(op)) {
4796 continue;
4797 }
4798
4799 attr_type_str = objprop_get_attribute_type_string(op);
4800 if (!attr_type_str) {
4801 continue;
4802 }
4803 col_id = objprop_get_column_id(op);
4804 if (col_id < 0) {
4805 continue;
4806 }
4807 name = objprop_get_name(op);
4808 if (!name) {
4809 continue;
4810 }
4811 cell = objprop_create_cell_renderer(op);
4812 if (!cell) {
4813 continue;
4814 }
4815
4816 col = gtk_tree_view_column_new_with_attributes(name, cell,
4817 attr_type_str, col_id,
4818 NULL);
4819
4820 gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_GROW_ONLY);
4821 gtk_tree_view_column_set_resizable(col, TRUE);
4822 gtk_tree_view_column_set_reorderable(col, TRUE);
4823 if (objprop_is_sortable(op)) {
4824 gtk_tree_view_column_set_clickable(col, TRUE);
4825 gtk_tree_view_column_set_sort_column_id(col, col_id);
4826 } else {
4827 gtk_tree_view_column_set_clickable(col, FALSE);
4828 }
4829 gtk_tree_view_append_column(GTK_TREE_VIEW(view), col);
4830 objprop_set_treeview_column(op, col);
4831
4832 } property_page_objprop_iterate_end;
4833
4834 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
4835 gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
4836 g_signal_connect(sel, "changed",
4837 G_CALLBACK(property_page_selection_changed), pp);
4838 gtk_tree_selection_set_select_function(sel,
4839 property_page_selection_func, pp, NULL);
4840
4841 gtk_container_add(GTK_CONTAINER(scrollwin), view);
4842 pp->object_view = view;
4843
4844 if (!objtype_is_conserved(objtype)) {
4845 hbox = gtk_grid_new();
4846 gtk_grid_set_column_spacing(GTK_GRID(hbox), 4);
4847 gtk_container_add(GTK_CONTAINER(vbox), hbox);
4848
4849 button = gtk_button_new();
4850 image = gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_BUTTON);
4851 gtk_button_set_image(GTK_BUTTON(button), image);
4852 gtk_button_set_label(GTK_BUTTON(button), _("Create"));
4853 gtk_size_group_add_widget(sizegroup, button);
4854 gtk_widget_set_tooltip_text(button,
4855 _("Pressing this button will create a new object of the "
4856 "same type as the current property page and add it to "
4857 "the page. The specific type and count of the objects "
4858 "is taken from the editor tool state. So for example, "
4859 "the \"tool value\" of the unit tool and its \"count\" "
4860 "parameter affect unit creation."));
4861 g_signal_connect(button, "clicked",
4862 G_CALLBACK(property_page_create_button_clicked), pp);
4863 gtk_container_add(GTK_CONTAINER(hbox), button);
4864
4865 button = gtk_button_new();
4866 image = gtk_image_new_from_stock(GTK_STOCK_REMOVE,
4867 GTK_ICON_SIZE_BUTTON);
4868 gtk_button_set_image(GTK_BUTTON(button), image);
4869 gtk_button_set_label(GTK_BUTTON(button), _("Destroy"));
4870 gtk_size_group_add_widget(sizegroup, button);
4871 gtk_widget_set_tooltip_text(button,
4872 _("Pressing this button will send a request to the server "
4873 "to destroy (i.e. erase) the objects selected in the object "
4874 "list."));
4875 g_signal_connect(button, "clicked",
4876 G_CALLBACK(property_page_destroy_button_clicked), pp);
4877 gtk_container_add(GTK_CONTAINER(hbox), button);
4878 }
4879
4880 /* Right side properties panel. */
4881
4882 hbox = gtk_grid_new();
4883 gtk_grid_set_column_spacing(GTK_GRID(hbox), 4);
4884 gtk_paned_pack2(GTK_PANED(paned), hbox, TRUE, TRUE);
4885
4886 vbox = gtk_grid_new();
4887 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
4888 GTK_ORIENTATION_VERTICAL);
4889 gtk_grid_set_row_spacing(GTK_GRID(vbox), 4);
4890 gtk_container_set_border_width(GTK_CONTAINER(vbox), 4);
4891 gtk_container_add(GTK_CONTAINER(hbox), vbox);
4892
4893 /* Extended property viewer to the right of the properties panel.
4894 * This needs to be created before property widgets, since some
4895 * might try to append themselves to this notebook. */
4896
4897 vbox2 = gtk_grid_new();
4898 gtk_widget_set_hexpand(vbox2, TRUE);
4899 gtk_widget_set_vexpand(vbox2, TRUE);
4900 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox2),
4901 GTK_ORIENTATION_VERTICAL);
4902 gtk_grid_set_row_spacing(GTK_GRID(vbox2), 4);
4903 gtk_container_add(GTK_CONTAINER(hbox), vbox2);
4904
4905 notebook = gtk_notebook_new();
4906 gtk_widget_set_vexpand(notebook, TRUE);
4907 gtk_widget_set_size_request(notebook, 256, -1);
4908 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
4909 gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
4910 gtk_container_add(GTK_CONTAINER(vbox2), notebook);
4911 pp->extviewer_notebook = notebook;
4912
4913 hsep = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
4914 gtk_container_add(GTK_CONTAINER(vbox2), hsep);
4915
4916 hbox2 = gtk_grid_new();
4917 gtk_container_set_border_width(GTK_CONTAINER(hbox2), 4);
4918 gtk_container_add(GTK_CONTAINER(vbox2), hbox2);
4919
4920 button = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
4921 gtk_size_group_add_widget(sizegroup, button);
4922 g_signal_connect_swapped(button, "clicked",
4923 G_CALLBACK(gtk_widget_hide_on_delete), pe->widget);
4924 gtk_container_add(GTK_CONTAINER(hbox2), button);
4925
4926 /* Now create the properties panel. */
4927
4928 /* TRANS: %s is a type of object that can be edited, such as "Tile",
4929 * "Unit", "Start Position", etc. */
4930 title = g_strdup_printf(_("%s Properties"),
4931 objtype_get_name(objtype));
4932 frame = gtk_frame_new(title);
4933 g_free(title);
4934 gtk_widget_set_size_request(frame, 256, -1);
4935 gtk_container_add(GTK_CONTAINER(vbox), frame);
4936
4937 scrollwin = gtk_scrolled_window_new(NULL, NULL);
4938 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollwin),
4939 GTK_SHADOW_NONE);
4940 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollwin),
4941 GTK_POLICY_AUTOMATIC,
4942 GTK_POLICY_AUTOMATIC);
4943 gtk_container_add(GTK_CONTAINER(frame), scrollwin);
4944
4945 vbox2 = gtk_grid_new();
4946 gtk_widget_set_vexpand(vbox2, TRUE);
4947 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox2),
4948 GTK_ORIENTATION_VERTICAL);
4949 gtk_grid_set_row_spacing(GTK_GRID(vbox2), 4);
4950 gtk_container_set_border_width(GTK_CONTAINER(vbox2), 4);
4951 gtk_container_add(GTK_CONTAINER(scrollwin), vbox2);
4952
4953 property_page_objprop_iterate(pp, op) {
4954 if (!objprop_has_widget(op)) {
4955 continue;
4956 }
4957 w = objprop_get_widget(op);
4958 if (!w) {
4959 continue;
4960 }
4961 gtk_container_add(GTK_CONTAINER(vbox2), w);
4962 tooltip = objprop_get_tooltip(op);
4963 if (NULL != tooltip) {
4964 gtk_widget_set_tooltip_text(w, tooltip);
4965 }
4966 } property_page_objprop_iterate_end;
4967
4968 hbox2 = gtk_grid_new();
4969 gtk_widget_set_margin_top(hbox2, 4);
4970 gtk_widget_set_margin_bottom(hbox2, 4);
4971 gtk_grid_set_column_spacing(GTK_GRID(hbox2), 4);
4972 gtk_container_add(GTK_CONTAINER(vbox), hbox2);
4973
4974 label = gtk_label_new(_("Filter:"));
4975 gtk_container_add(GTK_CONTAINER(hbox2), label);
4976
4977 entry = gtk_entry_new();
4978 gtk_widget_set_tooltip_text(entry,
4979 _("Enter a filter string to limit which properties are shown. "
4980 "The filter is one or more text patterns separated by | "
4981 "(\"or\") or & (\"and\"). The symbol & has higher precedence "
4982 "than |. A pattern may also be negated by prefixing it with !."));
4983 g_signal_connect(entry, "changed",
4984 G_CALLBACK(property_page_quick_find_entry_changed), pp);
4985 gtk_container_add(GTK_CONTAINER(hbox2), entry);
4986
4987 hbox2 = gtk_grid_new();
4988 gtk_grid_set_column_spacing(GTK_GRID(hbox2), 4);
4989 gtk_container_add(GTK_CONTAINER(vbox), hbox2);
4990
4991 button = gtk_button_new_from_stock(GTK_STOCK_REFRESH);
4992 gtk_size_group_add_widget(sizegroup, button);
4993 gtk_widget_set_tooltip_text(button,
4994 _("Pressing this button will reset all modified properties of "
4995 "the selected objects to their current values (the values "
4996 "they have on the server)."));
4997 g_signal_connect(button, "clicked",
4998 G_CALLBACK(property_page_refresh_button_clicked), pp);
4999 gtk_container_add(GTK_CONTAINER(hbox2), button);
5000
5001 button = gtk_button_new_from_stock(GTK_STOCK_APPLY);
5002 gtk_size_group_add_widget(sizegroup, button);
5003 gtk_widget_set_tooltip_text(button,
5004 _("Pressing this button will send all modified properties of "
5005 "the objects selected in the object list to the server. "
5006 "Modified properties' names are shown in red in the properties "
5007 "panel."));
5008 g_signal_connect(button, "clicked",
5009 G_CALLBACK(property_page_apply_button_clicked), pp);
5010 gtk_container_add(GTK_CONTAINER(hbox2), button);
5011
5012 return pp;
5013}
5014
5015/************************************************************************/
5018 static const char *property_page_get_name(const struct property_page *pp)
5019{
5020 if (!pp) {
5021 return "";
5022 }
5023 return objtype_get_name(property_page_get_objtype(pp));
5024}
5025
5026/************************************************************************/
5029static enum editor_object_type
5030property_page_get_objtype(const struct property_page *pp)
5031{
5032 if (!pp) {
5033 return -1;
5034 }
5035 return pp->objtype;
5036}
5037
5038/************************************************************************/
5046 static GdkPixbuf *create_tile_pixbuf(const struct tile *ptile)
5047{
5048 return create_pixbuf_from_layers(ptile, NULL, NULL, LAYER_CATEGORY_TILE);
5049}
5050
5051/************************************************************************/
5058 static GdkPixbuf *create_unit_pixbuf(const struct unit *punit)
5059{
5060 return create_pixbuf_from_layers(NULL, punit, NULL, LAYER_CATEGORY_UNIT);
5061}
5062
5063/************************************************************************/
5070 static GdkPixbuf *create_city_pixbuf(const struct city *pcity)
5071{
5072 return create_pixbuf_from_layers(city_tile(pcity), NULL, pcity,
5073 LAYER_CATEGORY_CITY);
5074}
5075
5076/************************************************************************/
5084 static GdkPixbuf *create_pixbuf_from_layers(const struct tile *ptile,
5085 const struct unit *punit,
5086 const struct city *pcity,
5087 enum layer_category category)
5088{
5089 struct canvas canvas = FC_STATIC_CANVAS_INIT;
5090 int h, fh, fw, canvas_x, canvas_y;
5091 GdkPixbuf *pixbuf;
5092 cairo_t *cr;
5093
5094 fw = tileset_full_tile_width(tileset);
5095 fh = tileset_full_tile_height(tileset);
5096 h = tileset_tile_height(tileset);
5097
5098 canvas.surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, fw, fh);
5099
5100 cr = cairo_create(canvas.surface);
5101 cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
5102 cairo_paint(cr);
5103 cairo_destroy(cr);
5104
5105 canvas_x = 0;
5106 canvas_y = 0;
5107
5108 canvas_y += (fh - h);
5109
5110 mapview_layer_iterate(layer) {
5111 if (tileset_layer_in_category(layer, category)) {
5112 put_one_element(&canvas, 1.0, layer,
5113 ptile, NULL, NULL, punit, pcity,
5114 canvas_x, canvas_y, NULL, NULL);
5115 }
5116 } mapview_layer_iterate_end
5117 pixbuf = surface_get_pixbuf(canvas.surface, fw, fh);
5118 cairo_surface_destroy(canvas.surface);
5119
5120 return pixbuf;
5121}
5122
5123/************************************************************************/
5126 static void property_page_clear_objbinds(struct property_page *pp)
5127{
5128 if (!pp) {
5129 return;
5130 }
5131
5132 gtk_list_store_clear(pp->object_store);
5133 objbind_hash_clear(pp->objbind_table);
5134 property_page_set_focused_objbind(pp, NULL);
5135}
5136
5137/************************************************************************/
5141 static void property_page_add_objbind(struct property_page *pp,
5142 gpointer object_data)
5143{
5144 struct objbind *ob;
5145 enum editor_object_type objtype;
5146 int id;
5147
5148 if (!pp) {
5149 return;
5150 }
5151
5152 objtype = property_page_get_objtype(pp);
5153 id = objtype_get_id_from_object(objtype, object_data);
5154 if (id < 0) {
5155 return;
5156 }
5157
5158 if (objbind_hash_lookup(pp->objbind_table, id, NULL)) {
5159 /* Object already exists. */
5160 return;
5161 }
5162
5163 ob = objbind_new(objtype, object_data);
5164 if (!ob) {
5165 return;
5166 }
5167
5168 objbind_bind_properties(ob, pp);
5169
5170 objbind_hash_insert(pp->objbind_table, ob->object_id, ob);
5171}
5172
5173/************************************************************************/
5177 static void property_page_add_objbinds_from_tile(struct property_page *pp,
5178 const struct tile *ptile)
5179{
5180
5181 if (!pp || !ptile) {
5182 return;
5183 }
5184
5185 switch (property_page_get_objtype(pp)) {
5186 case OBJTYPE_TILE:
5187 property_page_add_objbind(pp, (gpointer) ptile);
5188 return;
5189
5190 case OBJTYPE_STARTPOS:
5191 {
5192 struct startpos *psp = map_startpos_get(ptile);
5193
5194 if (NULL != psp) {
5195 property_page_add_objbind(pp, map_startpos_get(ptile));
5196 }
5197 }
5198 return;
5199
5200 case OBJTYPE_UNIT:
5201 unit_list_iterate(ptile->units, punit) {
5202 property_page_add_objbind(pp, punit);
5203 } unit_list_iterate_end;
5204 return;
5205
5206 case OBJTYPE_CITY:
5207 if (tile_city(ptile)) {
5208 property_page_add_objbind(pp, tile_city(ptile));
5209 }
5210 return;
5211
5212 case OBJTYPE_PLAYER:
5213 case OBJTYPE_GAME:
5214 return;
5215
5216 case NUM_OBJTYPES:
5217 break;
5218 }
5219
5220 log_error("%s(): Unhandled page object type %s (nb %d).", __FUNCTION__,
5221 objtype_get_name(property_page_get_objtype(pp)),
5222 property_page_get_objtype(pp));
5223}
5224
5225/************************************************************************/
5231 static bool property_page_set_store_value(struct property_page *pp,
5232 struct objprop *op,
5233 struct objbind *ob,
5234 GtkTreeIter *iter)
5235{
5236 int col_id;
5237 struct propval *pv;
5238 enum value_types valtype;
5239 char buf[128], *p;
5240 GdkPixbuf *pixbuf = NULL;
5241 GtkListStore *store;
5242 gchar *buf2;
5243
5244 if (!pp || !pp->object_store || !op || !ob) {
5245 return FALSE;
5246 }
5247
5248 if (!objprop_show_in_listview(op)) {
5249 return FALSE;
5250 }
5251
5252 col_id = objprop_get_column_id(op);
5253 if (col_id < 0) {
5254 return FALSE;
5255 }
5256
5257 pv = objbind_get_value_from_object(ob, op);
5258 if (!pv) {
5259 return FALSE;
5260 }
5261
5262 valtype = objprop_get_valtype(op);
5263 store = pp->object_store;
5264
5265 switch (valtype) {
5266 case VALTYPE_NONE:
5267 break;
5268 case VALTYPE_INT:
5269 gtk_list_store_set(store, iter, col_id, pv->data.v_int, -1);
5270 break;
5271 case VALTYPE_BOOL:
5272 /* Set as translated string, not as untranslated G_TYPE_BOOLEAN */
5273 gtk_list_store_set(store, iter, col_id, propval_as_string(pv), -1);
5274 break;
5275 case VALTYPE_STRING:
5276 if (fc_strlcpy(buf, pv->data.v_string, 28) >= 28) {
5277 sz_strlcat(buf, "...");
5278 }
5279 for (p = buf; *p; p++) {
5280 if (*p == '\n' || *p == '\t' || *p == '\r') {
5281 *p = ' ';
5282 }
5283 }
5284 gtk_list_store_set(store, iter, col_id, buf, -1);
5285 break;
5286 case VALTYPE_PIXBUF:
5287 gtk_list_store_set(store, iter, col_id, pv->data.v_pixbuf, -1);
5288 break;
5289 case VALTYPE_BUILT_ARRAY:
5290 case VALTYPE_INVENTIONS_ARRAY:
5291 case VALTYPE_BV_SPECIAL:
5292 case VALTYPE_BV_ROADS:
5293 case VALTYPE_BV_BASES:
5294 case VALTYPE_NATION_HASH:
5295 buf2 = propval_as_string(pv);
5296 gtk_list_store_set(store, iter, col_id, buf2, -1);
5297 g_free(buf2);
5298 break;
5299 case VALTYPE_NATION:
5300 pixbuf = get_flag(pv->data.v_nation);
5301 gtk_list_store_set(store, iter, col_id, pixbuf, -1);
5302 if (pixbuf) {
5303 g_object_unref(pixbuf);
5304 }
5305 break;
5306 case VALTYPE_GOV:
5307 pixbuf = sprite_get_pixbuf(get_government_sprite(tileset, pv->data.v_gov));
5308 gtk_list_store_set(store, iter, col_id, pixbuf, -1);
5309 if (pixbuf) {
5310 g_object_unref(pixbuf);
5311 }
5312 break;
5313 case VALTYPE_TILE_VISION_DATA:
5314 break;
5315 }
5316
5317 propval_free(pv);
5318
5319 return TRUE;
5320}
5321
5322/************************************************************************/
5326 static void property_page_fill_widgets(struct property_page *pp)
5327{
5328 struct objbind *focused;
5329
5330 if (!pp || !pp->objbind_table) {
5331 return;
5332 }
5333
5334 if (pp->object_store) {
5335 GtkTreeIter iter;
5336 GtkTreeRowReference *rr;
5337 GtkTreeModel *model;
5338 GtkTreePath *path;
5339
5340 model = GTK_TREE_MODEL(pp->object_store);
5341
5342 property_page_objbind_iterate(pp, ob) {
5343 if (objbind_get_rowref(ob)) {
5344 continue;
5345 }
5346 gtk_list_store_append(pp->object_store, &iter);
5347 gtk_list_store_set(pp->object_store, &iter, 0, ob, -1);
5348 path = gtk_tree_model_get_path(model, &iter);
5349 rr = gtk_tree_row_reference_new(model, path);
5350 gtk_tree_path_free(path);
5351 objbind_set_rowref(ob, rr);
5352
5353 property_page_objprop_iterate(pp, op) {
5354 property_page_set_store_value(pp, op, ob, &iter);
5355 } property_page_objprop_iterate_end;
5356 } property_page_objbind_iterate_end;
5357
5358 if (gtk_tree_model_get_iter_first(model, &iter)) {
5359 GtkTreeSelection *sel;
5360 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(pp->object_view));
5361 gtk_tree_selection_select_iter(sel, &iter);
5362 }
5363 }
5364
5365 focused = property_page_get_focused_objbind(pp);
5366 property_page_objprop_iterate(pp, op) {
5367 objprop_refresh_widget(op, focused);
5368 } property_page_objprop_iterate_end;
5369}
5370
5371/************************************************************************/
5375 static struct objbind *property_page_get_focused_objbind(struct property_page *pp)
5376{
5377 if (!pp) {
5378 return NULL;
5379 }
5380 return pp->focused_objbind;
5381}
5382
5383/************************************************************************/
5387 static void property_page_set_focused_objbind(struct property_page *pp,
5388 struct objbind *ob)
5389{
5390 if (!pp) {
5391 return;
5392 }
5393 pp->focused_objbind = ob;
5394}
5395
5396/************************************************************************/
5400 static struct objbind *property_page_get_objbind(struct property_page *pp,
5401 int object_id)
5402{
5403 struct objbind *ob;
5404
5405 if (!pp || !pp->objbind_table) {
5406 return NULL;
5407 }
5408
5409 objbind_hash_lookup(pp->objbind_table, object_id, &ob);
5410 return ob;
5411}
5412
5413/************************************************************************/
5417 static void property_page_load_tiles(struct property_page *pp,
5418 const struct tile_list *tiles)
5419{
5420 if (!pp || !tiles) {
5421 return;
5422 }
5423
5424 tile_list_iterate(tiles, ptile) {
5425 property_page_add_objbinds_from_tile(pp, ptile);
5426 } tile_list_iterate_end;
5427
5428 property_page_fill_widgets(pp);
5429}
5430
5431/************************************************************************/
5434 static int property_page_get_num_objbinds(const struct property_page *pp)
5435{
5436 if (!pp || !pp->objbind_table) {
5437 return 0;
5438 }
5439 return objbind_hash_size(pp->objbind_table);
5440}
5441
5442/************************************************************************/
5446 static void property_page_change_value(struct property_page *pp,
5447 struct objprop *op,
5448 struct propval *pv)
5449{
5450 GtkTreeSelection *sel;
5451 GtkTreeModel *model;
5452 GList *rows, *p;
5453 GtkTreePath *path;
5454 GtkTreeIter iter;
5455 struct objbind *ob;
5456 bool changed = FALSE;
5457
5458 if (!pp || !op || !pp->object_view) {
5459 return;
5460 }
5461
5462 if (objprop_is_readonly(op)) {
5463 return;
5464 }
5465
5466 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(pp->object_view));
5467 rows = gtk_tree_selection_get_selected_rows(sel, &model);
5468
5469 for (p = rows; p != NULL; p = p->next) {
5470 path = p->data;
5471 if (gtk_tree_model_get_iter(model, &iter, path)) {
5472 gtk_tree_model_get(model, &iter, 0, &ob, -1);
5473 changed |= objbind_set_modified_value(ob, op, pv);
5474 }
5475 gtk_tree_path_free(path);
5476 }
5477 g_list_free(rows);
5478
5479 if (changed) {
5480 ob = property_page_get_focused_objbind(pp);
5481 objprop_refresh_widget(op, ob);
5482 }
5483}
5484
5485/************************************************************************/
5488 static void property_page_send_values(struct property_page *pp)
5489{
5490 GtkTreeSelection *sel;
5491 GtkTreeModel *model;
5492 GList *rows, *p;
5493 GtkTreePath *path;
5494 GtkTreeIter iter;
5495 struct objbind *ob;
5496 union packetdata packet;
5497 struct connection *my_conn = &client.conn;
5498
5499 if (!pp || !pp->object_view) {
5500 return;
5501 }
5502
5503 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(pp->object_view));
5504 if (gtk_tree_selection_count_selected_rows(sel) < 1) {
5505 return;
5506 }
5507
5508 packet = property_page_new_packet(pp);
5509 if (!packet.pointers.v_pointer1) {
5510 return;
5511 }
5512
5513 rows = gtk_tree_selection_get_selected_rows(sel, &model);
5514 connection_do_buffer(my_conn);
5515 for (p = rows; p != NULL; p = p->next) {
5516 path = p->data;
5517 if (gtk_tree_model_get_iter(model, &iter, path)) {
5518 gtk_tree_model_get(model, &iter, 0, &ob, -1);
5519 if (objbind_has_modified_properties(ob)) {
5520 objbind_pack_current_values(ob, packet);
5521 property_page_objprop_iterate(pp, op) {
5522 if (objprop_is_readonly(op)) {
5523 continue;
5524 }
5525 objbind_pack_modified_value(ob, op, packet);
5526 } property_page_objprop_iterate_end;
5527 property_page_send_packet(pp, packet);
5528 }
5529 }
5530 gtk_tree_path_free(path);
5531 }
5532 connection_do_unbuffer(my_conn);
5533 g_list_free(rows);
5534
5535 property_page_free_packet(pp, packet);
5536}
5537
5538/************************************************************************/
5542 static union packetdata property_page_new_packet(struct property_page *pp)
5543{
5544 union packetdata packet;
5545
5546 packet.pointers.v_pointer2 = NULL;
5547
5548 if (!pp) {
5549 packet.pointers.v_pointer1 = NULL;
5550 return packet;
5551 }
5552
5553 switch (property_page_get_objtype(pp)) {
5554 case OBJTYPE_TILE:
5555 packet.tile = fc_calloc(1, sizeof(*packet.tile));
5556 break;
5557 case OBJTYPE_STARTPOS:
5558 packet.startpos = fc_calloc(1, sizeof(*packet.startpos));
5559 break;
5560 case OBJTYPE_UNIT:
5561 packet.unit = fc_calloc(1, sizeof(*packet.unit));
5562 break;
5563 case OBJTYPE_CITY:
5564 packet.city = fc_calloc(1, sizeof(*packet.city));
5565 break;
5566 case OBJTYPE_PLAYER:
5567 packet.player = fc_calloc(1, sizeof(*packet.player));
5568 break;
5569 case OBJTYPE_GAME:
5570 packet.game.game = fc_calloc(1, sizeof(*packet.game.game));
5571 packet.game.desc = fc_calloc(1, sizeof(*packet.game.desc));
5572 break;
5573 case NUM_OBJTYPES:
5574 break;
5575 }
5576
5577 return packet;
5578}
5579
5580/************************************************************************/
5583 static void property_page_send_packet(struct property_page *pp,
5584 union packetdata packet)
5585{
5586 struct connection *my_conn = &client.conn;
5587
5588 if (!pp || !packet.pointers.v_pointer1) {
5589 return;
5590 }
5591
5592 switch (property_page_get_objtype(pp)) {
5593 case OBJTYPE_TILE:
5594 send_packet_edit_tile(my_conn, packet.tile);
5595 return;
5596 case OBJTYPE_STARTPOS:
5597 send_packet_edit_startpos_full(my_conn, packet.startpos);
5598 return;
5599 case OBJTYPE_UNIT:
5600 send_packet_edit_unit(my_conn, packet.unit);
5601 return;
5602 case OBJTYPE_CITY:
5603 send_packet_edit_city(my_conn, packet.city);
5604 return;
5605 case OBJTYPE_PLAYER:
5606 send_packet_edit_player(my_conn, packet.player);
5607 return;
5608 case OBJTYPE_GAME:
5609 send_packet_edit_game(my_conn, packet.game.game);
5610 send_packet_edit_scenario_desc(my_conn, packet.game.desc);
5611 return;
5612 case NUM_OBJTYPES:
5613 break;
5614 }
5615
5616 log_error("%s(): Unhandled object type %s (nb %d).",
5617 __FUNCTION__, objtype_get_name(property_page_get_objtype(pp)),
5618 property_page_get_objtype(pp));
5619}
5620
5621/************************************************************************/
5624 static void property_page_free_packet(struct property_page *pp,
5625 union packetdata packet)
5626{
5627 if (!packet.pointers.v_pointer1) {
5628 return;
5629 }
5630
5631 free(packet.pointers.v_pointer1);
5632 packet.pointers.v_pointer1 = NULL;
5633
5634 if (packet.pointers.v_pointer2 != NULL) {
5635 free(packet.pointers.v_pointer2);
5636 packet.pointers.v_pointer2 = NULL;
5637 }
5638}
5639
5640/************************************************************************/
5644 static void property_page_reset_objbinds(struct property_page *pp)
5645{
5646 GtkTreeSelection *sel;
5647 GtkTreeModel *model;
5648 GtkTreeIter iter;
5649 GtkTreePath *path;
5650 GList *rows, *p;
5651 struct objbind *ob;
5652
5653 if (!pp || !pp->object_view) {
5654 return;
5655 }
5656
5657 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(pp->object_view));
5658 if (gtk_tree_selection_count_selected_rows(sel) < 1) {
5659 return;
5660 }
5661
5662 rows = gtk_tree_selection_get_selected_rows(sel, &model);
5663 for (p = rows; p != NULL; p = p->next) {
5664 path = p->data;
5665 if (gtk_tree_model_get_iter(model, &iter, path)) {
5666 gtk_tree_model_get(model, &iter, 0, &ob, -1);
5667 objbind_clear_all_modified_values(ob);
5668 property_page_objprop_iterate(pp, op) {
5669 property_page_set_store_value(pp, op, ob, &iter);
5670 } property_page_objprop_iterate_end;
5671 }
5672 gtk_tree_path_free(path);
5673 }
5674 g_list_free(rows);
5675
5676 ob = property_page_get_focused_objbind(pp);
5677 property_page_objprop_iterate(pp, op) {
5678 objprop_refresh_widget(op, ob);
5679 } property_page_objprop_iterate_end;
5680}
5681
5682/************************************************************************/
5685 static void property_page_destroy_objects(struct property_page *pp)
5686{
5687 GtkTreeSelection *sel;
5688 GtkTreeModel *model;
5689 GtkTreeIter iter;
5690 GtkTreePath *path;
5691 GList *rows, *p;
5692 struct objbind *ob;
5693 struct connection *my_conn = &client.conn;
5694
5695 if (!pp || !pp->object_view) {
5696 return;
5697 }
5698
5699 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(pp->object_view));
5700 if (gtk_tree_selection_count_selected_rows(sel) < 1) {
5701 return;
5702 }
5703
5704 rows = gtk_tree_selection_get_selected_rows(sel, &model);
5705 connection_do_buffer(my_conn);
5706 for (p = rows; p != NULL; p = p->next) {
5707 path = p->data;
5708 if (gtk_tree_model_get_iter(model, &iter, path)) {
5709 gtk_tree_model_get(model, &iter, 0, &ob, -1);
5710 objbind_request_destroy_object(ob);
5711 }
5712 gtk_tree_path_free(path);
5713 }
5714 connection_do_unbuffer(my_conn);
5715 g_list_free(rows);
5716}
5717
5718/************************************************************************/
5724 static void property_page_create_objects(struct property_page *pp,
5725 struct tile_list *hint_tiles)
5726{
5727 enum editor_object_type objtype;
5728 int apno, value, count, size;
5729 int tag;
5730 struct connection *my_conn = &client.conn;
5731 struct tile *ptile = NULL;
5732 struct player *pplayer;
5733
5734 if (!pp) {
5735 return;
5736 }
5737
5738 objtype = property_page_get_objtype(pp);
5739 if (objtype_is_conserved(objtype)) {
5740 return;
5741 }
5742
5743 tag = get_next_unique_tag();
5744 count = 1;
5745
5746 switch (objtype) {
5747 case OBJTYPE_STARTPOS:
5748 if (hint_tiles) {
5749 tile_list_iterate(hint_tiles, atile) {
5750 if (NULL == map_startpos_get(atile)) {
5751 ptile = atile;
5752 break;
5753 }
5754 } tile_list_iterate_end;
5755 }
5756
5757 if (NULL == ptile) {
5758 ptile = get_center_tile_mapcanvas();
5759 }
5760
5761 if (NULL == ptile) {
5762 break;
5763 }
5764
5765 dsend_packet_edit_startpos(my_conn, tile_index(ptile), FALSE, tag);
5766 break;
5767
5768 case OBJTYPE_UNIT:
5769 if (hint_tiles) {
5770 tile_list_iterate(hint_tiles, atile) {
5771 if (can_create_unit_at_tile(atile)) {
5772 ptile = atile;
5773 break;
5774 }
5775 } tile_list_iterate_end;
5776 }
5777
5778 if (!ptile) {
5779 struct unit *punit;
5780 property_page_objbind_iterate(pp, ob) {
5781 punit = objbind_get_object(ob);
5782 if (punit && can_create_unit_at_tile(unit_tile(punit))) {
5783 ptile = unit_tile(punit);
5784 break;
5785 }
5786 } property_page_objbind_iterate_end;
5787 }
5788
5789 if (!ptile) {
5790 ptile = get_center_tile_mapcanvas();
5791 }
5792
5793 if (!ptile) {
5794 break;
5795 }
5796
5797 apno = editor_tool_get_applied_player(ETT_UNIT);
5798 count = editor_tool_get_count(ETT_UNIT);
5799 value = editor_tool_get_value(ETT_UNIT);
5800 dsend_packet_edit_unit_create(my_conn, apno, tile_index(ptile),
5801 value, count, tag);
5802 break;
5803
5804 case OBJTYPE_CITY:
5805 apno = editor_tool_get_applied_player(ETT_CITY);
5806 pplayer = player_by_number(apno);
5807 if (pplayer && hint_tiles) {
5808 tile_list_iterate(hint_tiles, atile) {
5809 if (!is_enemy_unit_tile(atile, pplayer)
5810 && city_can_be_built_here(atile, NULL, FALSE)) {
5811 ptile = atile;
5812 break;
5813 }
5814 } tile_list_iterate_end;
5815 }
5816
5817 if (!ptile) {
5818 ptile = get_center_tile_mapcanvas();
5819 }
5820
5821 if (!ptile) {
5822 break;
5823 }
5824
5825 size = editor_tool_get_size(ETT_CITY);
5826 dsend_packet_edit_city_create(my_conn, apno, tile_index(ptile),
5827 size, tag);
5828 break;
5829
5830 case OBJTYPE_PLAYER:
5831 dsend_packet_edit_player_create(my_conn, tag);
5832 break;
5833
5834 case OBJTYPE_TILE:
5835 case OBJTYPE_GAME:
5836 case NUM_OBJTYPES:
5837 break;
5838 }
5839
5840 property_page_store_creation_tag(pp, tag, count);
5841}
5842
5843/************************************************************************/
5848 static void property_page_object_changed(struct property_page *pp,
5849 int object_id,
5850 bool removed)
5851{
5852 struct objbind *ob;
5853 GtkTreeRowReference *rr;
5854
5855 ob = property_page_get_objbind(pp, object_id);
5856 if (!ob) {
5857 return;
5858 }
5859
5860 rr = objbind_get_rowref(ob);
5861 if (rr && gtk_tree_row_reference_valid(rr)) {
5862 GtkTreePath *path;
5863 GtkTreeIter iter;
5864 GtkTreeModel *model;
5865
5866 model = GTK_TREE_MODEL(pp->object_store);
5867 path = gtk_tree_row_reference_get_path(rr);
5868
5869 if (gtk_tree_model_get_iter(model, &iter, path)) {
5870 if (removed) {
5871 gtk_list_store_remove(pp->object_store, &iter);
5872 } else {
5873 property_page_objprop_iterate(pp, op) {
5874 property_page_set_store_value(pp, op, ob, &iter);
5875 } property_page_objprop_iterate_end;
5876 }
5877 }
5878
5879 gtk_tree_path_free(path);
5880 }
5881
5882 if (removed) {
5883 objbind_hash_remove(pp->objbind_table, object_id);
5884 return;
5885 }
5886
5887 if (ob == property_page_get_focused_objbind(pp)) {
5888 property_page_objprop_iterate(pp, op) {
5889 objprop_refresh_widget(op, ob);
5890 } property_page_objprop_iterate_end;
5891 }
5892}
5893
5894/************************************************************************/
5900 static void property_page_object_created(struct property_page *pp,
5901 int tag, int object_id)
5902{
5903 gpointer object;
5904 enum editor_object_type objtype;
5905
5906 if (!property_page_tag_is_known(pp, tag)) {
5907 return;
5908 }
5909 property_page_remove_creation_tag(pp, tag);
5910
5911 objtype = property_page_get_objtype(pp);
5912 object = objtype_get_object_from_id(objtype, object_id);
5913
5914 if (!object) {
5915 return;
5916 }
5917
5918 property_page_add_objbind(pp, object);
5919 property_page_fill_widgets(pp);
5920}
5921
5922/************************************************************************/
5926 static void property_page_add_extviewer(struct property_page *pp,
5927 struct extviewer *ev)
5928{
5929 GtkWidget *w;
5930
5931 if (!pp || !ev) {
5932 return;
5933 }
5934
5935 w = extviewer_get_view_widget(ev);
5936 if (!w) {
5937 return;
5938 }
5939 gtk_notebook_append_page(GTK_NOTEBOOK(pp->extviewer_notebook), w, NULL);
5940}
5941
5942/************************************************************************/
5946 static void property_page_show_extviewer(struct property_page *pp,
5947 struct extviewer *ev)
5948{
5949 GtkWidget *w;
5950 GtkNotebook *notebook;
5951 int page;
5952
5953 if (!pp || !ev) {
5954 return;
5955 }
5956
5957 w = extviewer_get_view_widget(ev);
5958 if (!w) {
5959 return;
5960 }
5961
5962 notebook = GTK_NOTEBOOK(pp->extviewer_notebook);
5963 page = gtk_notebook_page_num(notebook, w);
5964 gtk_notebook_set_current_page(notebook, page);
5965}
5966
5967/************************************************************************/
5971 static void property_page_store_creation_tag(struct property_page *pp,
5972 int tag, int count)
5973{
5974 if (!pp || !pp->tag_table) {
5975 return;
5976 }
5977
5978 if (stored_tag_hash_lookup(pp->tag_table, tag, NULL)) {
5979 log_error("Attempted to insert object creation tag %d "
5980 "twice into tag table for property page %p (%d %s).",
5981 tag, pp, property_page_get_objtype(pp),
5982 property_page_get_name(pp));
5983 return;
5984 }
5985
5986 stored_tag_hash_insert(pp->tag_table, tag, count);
5987}
5988
5989/************************************************************************/
5993 static void property_page_remove_creation_tag(struct property_page *pp,
5994 int tag)
5995{
5996 int count;
5997
5998 if (!pp || !pp->tag_table) {
5999 return;
6000 }
6001
6002 if (stored_tag_hash_lookup(pp->tag_table, tag, &count)) {
6003 if (0 >= --count) {
6004 stored_tag_hash_remove(pp->tag_table, tag);
6005 }
6006 }
6007}
6008
6009/************************************************************************/
6012 static bool property_page_tag_is_known(struct property_page *pp, int tag)
6013{
6014 if (!pp || !pp->tag_table) {
6015 return FALSE;
6016 }
6017 return stored_tag_hash_lookup(pp->tag_table, tag, NULL);
6018}
6019
6020/************************************************************************/
6023 static void property_page_clear_tags(struct property_page *pp)
6024{
6025 if (!pp || !pp->tag_table) {
6026 return;
6027 }
6028 stored_tag_hash_clear(pp->tag_table);
6029}
6030
6031/************************************************************************/
6034 static void property_page_apply_button_clicked(GtkButton *button,
6035 gpointer userdata)
6036{
6037 struct property_page *pp = userdata;
6038 property_page_send_values(pp);
6039}
6040
6041/************************************************************************/
6045 static void property_page_refresh_button_clicked(GtkButton *button,
6046 gpointer userdata)
6047{
6048 struct property_page *pp = userdata;
6049 property_page_reset_objbinds(pp);
6050}
6051
6052/************************************************************************/
6055 static void property_page_create_button_clicked(GtkButton *button,
6056 gpointer userdata)
6057{
6058 struct property_page *pp = userdata, *tile_pp;
6059 struct tile_list *tiles = NULL;
6060 struct tile *ptile;
6061
6062 if (!pp) {
6063 return;
6064 }
6065
6066 tile_pp = property_editor_get_page(pp->pe_parent, OBJTYPE_TILE);
6067 tiles = tile_list_new();
6068
6069 property_page_objbind_iterate(tile_pp, ob) {
6070 ptile = objbind_get_object(ob);
6071 if (ptile) {
6072 tile_list_append(tiles, ptile);
6073 }
6074 } property_page_objbind_iterate_end;
6075
6076 property_page_create_objects(pp, tiles);
6077 tile_list_destroy(tiles);
6078}
6079
6080/************************************************************************/
6083 static void property_page_destroy_button_clicked(GtkButton *button,
6084 gpointer userdata)
6085{
6086 struct property_page *pp = userdata;
6087 property_page_destroy_objects(pp);
6088}
6089
6090/************************************************************************/
6094 static bool property_editor_add_page(struct property_editor *pe,
6095 enum editor_object_type objtype)
6096{
6097 struct property_page *pp;
6098 GtkWidget *label;
6099 const char *name;
6100
6101 if (!pe || !pe->notebook) {
6102 return FALSE;
6103 }
6104
6105 if (!(objtype < NUM_OBJTYPES)) {
6106 return FALSE;
6107 }
6108
6109 pp = property_page_new(objtype, pe);
6110 if (!pp) {
6111 return FALSE;
6112 }
6113
6114 name = property_page_get_name(pp);
6115 label = gtk_label_new(name);
6116 gtk_notebook_append_page(GTK_NOTEBOOK(pe->notebook),
6117 pp->widget, label);
6118
6119 pe->property_pages[objtype] = pp;
6120
6121 return TRUE;
6122}
6123
6124/************************************************************************/
6127static struct property_page *
6128property_editor_get_page(struct property_editor *pe,
6129 enum editor_object_type objtype)
6130{
6131 if (!pe || !(objtype < NUM_OBJTYPES)) {
6132 return NULL;
6133 }
6134
6135 return pe->property_pages[objtype];
6136}
6137
6138/************************************************************************/
6141 static struct property_editor *property_editor_new(void)
6142{
6143 struct property_editor *pe;
6144 GtkWidget *win, *notebook, *vbox;
6145 enum editor_object_type objtype;
6146
6147 pe = fc_calloc(1, sizeof(*pe));
6148
6149 /* The property editor dialog window. */
6150
6151 win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
6152 gtk_window_set_title(GTK_WINDOW(win), _("Property Editor"));
6153 gtk_window_set_resizable(GTK_WINDOW(win), TRUE);
6154 gtk_window_set_default_size(GTK_WINDOW(win), 780, 560);
6155 gtk_window_set_position(GTK_WINDOW(win), GTK_WIN_POS_CENTER_ON_PARENT);
6156 gtk_window_set_transient_for(GTK_WINDOW(win), GTK_WINDOW(toplevel));
6157 gtk_window_set_destroy_with_parent(GTK_WINDOW(win), TRUE);
6158 gtk_window_set_type_hint(GTK_WINDOW(win), GDK_WINDOW_TYPE_HINT_DIALOG);
6159 gtk_container_set_border_width(GTK_CONTAINER(win), 4);
6160 g_signal_connect(win, "delete-event",
6161 G_CALLBACK(gtk_widget_hide_on_delete), NULL);
6162 pe->widget = win;
6163
6164 vbox = gtk_grid_new();
6165 gtk_container_add(GTK_CONTAINER(win), vbox);
6166
6167 /* Property pages. */
6168
6169 notebook = gtk_notebook_new();
6170 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), TRUE);
6171 gtk_container_add(GTK_CONTAINER(vbox), notebook);
6172 pe->notebook = notebook;
6173
6174 for (objtype = 0; objtype < NUM_OBJTYPES; objtype++) {
6175 property_editor_add_page(pe, objtype);
6176 }
6177
6178 return pe;
6179}
6180
6181/************************************************************************/
6184 struct property_editor *editprop_get_property_editor(void)
6185{
6186 if (!the_property_editor) {
6187 the_property_editor = property_editor_new();
6188 }
6189 return the_property_editor;
6190}
6191
6192/************************************************************************/
6195 void property_editor_load_tiles(struct property_editor *pe,
6196 const struct tile_list *tiles)
6197{
6198 struct property_page *pp;
6199 enum editor_object_type objtype;
6200 int i;
6201 const enum editor_object_type preferred[] = {
6202 OBJTYPE_CITY,
6203 OBJTYPE_UNIT,
6204 OBJTYPE_STARTPOS,
6205 OBJTYPE_TILE
6206 };
6207
6208 if (!pe || !tiles) {
6209 return;
6210 }
6211
6212 for (objtype = 0; objtype < NUM_OBJTYPES; objtype++) {
6213 pp = property_editor_get_page(pe, objtype);
6214 property_page_load_tiles(pp, tiles);
6215 }
6216
6217 for (i = 0; i < ARRAY_SIZE(preferred) - 1; i++) {
6218 pp = property_editor_get_page(pe, preferred[i]);
6219 if (property_page_get_num_objbinds(pp) > 0) {
6220 break;
6221 }
6222 }
6223 objtype = preferred[i];
6224 gtk_notebook_set_current_page(GTK_NOTEBOOK(pe->notebook), objtype);
6225}
6226
6227/************************************************************************/
6231 void property_editor_popup(struct property_editor *pe,
6232 enum editor_object_type objtype)
6233{
6234 if (!pe || !pe->widget) {
6235 return;
6236 }
6237
6238 gtk_widget_show_all(pe->widget);
6239
6240 gtk_window_present(GTK_WINDOW(pe->widget));
6241 if (objtype < NUM_OBJTYPES) {
6242 gtk_notebook_set_current_page(GTK_NOTEBOOK(pe->notebook), objtype);
6243 }
6244}
6245
6246/************************************************************************/
6249 void property_editor_popdown(struct property_editor *pe)
6250{
6251 if (!pe || !pe->widget) {
6252 return;
6253 }
6254 gtk_widget_hide(pe->widget);
6255}
6256
6257/************************************************************************/
6261 void property_editor_handle_object_changed(struct property_editor *pe,
6262 enum editor_object_type objtype,
6263 int object_id,
6264 bool remove)
6265{
6266 struct property_page *pp;
6267
6268 if (!pe) {
6269 return;
6270 }
6271
6272 if (!(objtype < NUM_OBJTYPES)) {
6273 return;
6274 }
6275
6276 pp = property_editor_get_page(pe, objtype);
6277 property_page_object_changed(pp, object_id, remove);
6278}
6279
6280/************************************************************************/
6283 void property_editor_handle_object_created(struct property_editor *pe,
6284 int tag, int object_id)
6285{
6286 enum editor_object_type objtype;
6287 struct property_page *pp;
6288
6289 for (objtype = 0; objtype < NUM_OBJTYPES; objtype++) {
6290 if (objtype_is_conserved(objtype)) {
6291 continue;
6292 }
6293 pp = property_editor_get_page(pe, objtype);
6294 property_page_object_created(pp, tag, object_id);
6295 }
6296}
6297
6298/************************************************************************/
6301 void property_editor_clear(struct property_editor *pe)
6302{
6303 enum editor_object_type objtype;
6304 struct property_page *pp;
6305
6306 if (!pe) {
6307 return;
6308 }
6309
6310 for (objtype = 0; objtype < NUM_OBJTYPES; objtype++) {
6311 pp = property_editor_get_page(pe, objtype);
6312 property_page_clear_objbinds(pp);
6313 property_page_clear_tags(pp);
6314 }
6315}
6316
6317/************************************************************************/
6321 void property_editor_reload(struct property_editor *pe,
6322 enum editor_object_type objtype)
6323{
6324 struct property_page *pp;
6325
6326 if (!pe) {
6327 return;
6328 }
6329
6330 pp = property_editor_get_page(pe, objtype);
6331 if (!pp) {
6332 return;
6333 }
6334
6335 property_page_clear_objbinds(pp);
6336
6337 switch (objtype) {
6338 case OBJTYPE_PLAYER:
6339 players_iterate(pplayer) {
6340 property_page_add_objbind(pp, pplayer);
6341 } players_iterate_end;
6342 break;
6343 case OBJTYPE_GAME:
6344 property_page_add_objbind(pp, &game);
6345 break;
6346 case OBJTYPE_TILE:
6347 case OBJTYPE_STARTPOS:
6348 case OBJTYPE_UNIT:
6349 case OBJTYPE_CITY:
6350 case NUM_OBJTYPES:
6351 break;
6352 }
6353
6354 property_page_fill_widgets(pp);
6355 gtk_notebook_set_current_page(GTK_NOTEBOOK(pe->notebook), objtype);
6356}
6357
6358/************************************************************************/
6369 static struct property_filter *property_filter_new(const char *filter)
6370{
6371 struct property_filter *pf;
6372 struct pf_conjunction *pfc;
6373 struct pf_pattern *pfp;
6374 int or_clause_count, and_clause_count;
6375 char *or_clauses[PF_MAX_CLAUSES], *and_clauses[PF_MAX_CLAUSES];
6376 const char *pattern;
6377 int i, j;
6378
6379 pf = fc_calloc(1, sizeof(*pf));
6380
6381 if (!filter || filter[0] == '\0') {
6382 return pf;
6383 }
6384
6385 or_clause_count = get_tokens(filter, or_clauses,
6386 PF_MAX_CLAUSES,
6387 PF_DISJUNCTION_SEPARATOR);
6388
6389 for (i = 0; i < or_clause_count; i++) {
6390 if (or_clauses[i][0] == '\0') {
6391 continue;
6392 }
6393 pfc = &pf->disjunction[pf->count];
6394
6395 and_clause_count = get_tokens(or_clauses[i], and_clauses,
6396 PF_MAX_CLAUSES,
6397 PF_CONJUNCTION_SEPARATOR);
6398
6399 for (j = 0; j < and_clause_count; j++) {
6400 if (and_clauses[j][0] == '\0') {
6401 continue;
6402 }
6403 pfp = &pfc->conjunction[pfc->count];
6404 pattern = and_clauses[j];
6405
6406 switch (pattern[0]) {
6407 case '!':
6408 pfp->negate = TRUE;
6409 pfp->text = fc_strdup(pattern + 1);
6410 break;
6411 default:
6412 pfp->text = fc_strdup(pattern);
6413 break;
6414 }
6415 pfc->count++;
6416 }
6417 free_tokens(and_clauses, and_clause_count);
6418 pf->count++;
6419 }
6420
6421 free_tokens(or_clauses, or_clause_count);
6422
6423 return pf;
6424}
6425
6426/************************************************************************/
6443 static bool property_filter_match(struct property_filter *pf,
6444 const struct objprop *op)
6445{
6446 struct pf_pattern *pfp;
6447 struct pf_conjunction *pfc;
6448 const char *name;
6449 bool match, or_result, and_result;
6450 int i, j;
6451
6452 if (!pf) {
6453 return TRUE;
6454 }
6455 if (!op) {
6456 return FALSE;
6457 }
6458
6459 name = objprop_get_name(op);
6460 if (!name) {
6461 return FALSE;
6462 }
6463
6464 if (pf->count < 1) {
6465 return TRUE;
6466 }
6467
6468 or_result = FALSE;
6469
6470 for (i = 0; i < pf->count; i++) {
6471 pfc = &pf->disjunction[i];
6472 and_result = TRUE;
6473 for (j = 0; j < pfc->count; j++) {
6474 pfp = &pfc->conjunction[j];
6475 match = (pfp->text[0] == '\0'
6476 || fc_strcasestr(name, pfp->text));
6477 if (pfp->negate) {
6478 match = !match;
6479 }
6480 and_result = and_result && match;
6481 if (!and_result) {
6482 break;
6483 }
6484 }
6485 or_result = or_result || and_result;
6486 if (or_result) {
6487 break;
6488 }
6489 }
6490
6491 return or_result;
6492}
6493
6494/************************************************************************/
6497 static void property_filter_free(struct property_filter *pf)
6498{
6499 struct pf_pattern *pfp;
6500 struct pf_conjunction *pfc;
6501 int i, j;
6502
6503 if (!pf) {
6504 return;
6505 }
6506
6507 for (i = 0; i < pf->count; i++) {
6508 pfc = &pf->disjunction[i];
6509 for (j = 0; j < pfc->count; j++) {
6510 pfp = &pfc->conjunction[j];
6511 if (pfp->text != NULL) {
6512 free(pfp->text);
6513 pfp->text = NULL;
6514 }
6515 }
6516 pfc->count = 0;
6517 }
6518 pf->count = 0;
6519 free(pf);
6520}
6521
6522/************************************************************************/
6525 const char *vision_layer_get_name(enum vision_layer vl)
6526{
6527 switch (vl) {
6528 case V_MAIN:
6529 /* TRANS: Vision layer name. Feel free to leave untranslated. */
6530 return _("Seen (Main)");
6531 case V_INVIS:
6532 /* TRANS: Vision layer name. Feel free to leave untranslated. */
6533 return _("Seen (Invis)");
6534 case V_SUBSURFACE:
6535 /* TRANS: Vision layer name. Feel free to leave untranslated. */
6536 return _("Seen (Subsurface)");
6537 case V_COUNT:
6538 break;
6539 }
6540
6541 log_error("%s(): Unrecognized vision layer %d.", __FUNCTION__, vl);
6542 return _("Unknown");
6543}
base_number
Base_type_id base_number(const struct base_type *pbase)
Definition base.c:92
base_count
Base_type_id base_count(void)
Definition base.c:109
dbv_isset
bool dbv_isset(const struct dbv *pdbv, int bit)
Definition bitvector.c:120
bitvector.h
BV_CLR_ALL
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
BV_SET
#define BV_SET(bv, bit)
Definition bitvector.h:81
BV_ARE_EQUAL
#define BV_ARE_EQUAL(vec1, vec2)
Definition bitvector.h:113
BV_ISSET
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
BV_CLR
#define BV_CLR(bv, bit)
Definition bitvector.h:86
canvas_y
struct canvas int int canvas_y
Definition canvas_g.h:43
canvas_x
struct canvas int canvas_x
Definition canvas_g.h:43
city_granary_size
int city_granary_size(int city_size)
Definition city.c:2095
city_can_be_built_here
bool city_can_be_built_here(const struct tile *ptile, const struct unit *punit, bool hut_test)
Definition city.c:1451
city_tile
#define city_tile(_pcity_)
Definition city.h:544
city_size_get
static citizens city_size_get(const struct city *pcity)
Definition city.h:549
city_owner
#define city_owner(_pcity_)
Definition city.h:543
MAX_CITY_SIZE
#define MAX_CITY_SIZE
Definition city.h:98
I_DESTROYED
#define I_DESTROYED
Definition city.h:240
I_NEVER
#define I_NEVER
Definition city.h:239
client
struct civclient client
Definition client_main.c:149
client_main.h
client_nation_is_in_current_set
bool client_nation_is_in_current_set(const struct nation_type *pnation)
Definition climisc.c:1491
climisc.h
connection_do_buffer
void connection_do_buffer(struct connection *pc)
Definition connection.c:323
connection_do_unbuffer
void connection_do_unbuffer(struct connection *pc)
Definition connection.c:335
punit
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:73
objtype
int objtype
Definition editgui_g.h:28
id
int int id
Definition editgui_g.h:28
editor_tool_get_size
int editor_tool_get_size(enum editor_tool_type ett)
Definition editor.c:1218
editor_tool_get_value
int editor_tool_get_value(enum editor_tool_type ett)
Definition editor.c:409
editor_tool_get_count
int editor_tool_get_count(enum editor_tool_type ett)
Definition editor.c:1252
editor_unit_virtual_create
struct unit * editor_unit_virtual_create(void)
Definition editor.c:1405
editor_tool_get_applied_player
int editor_tool_get_applied_player(enum editor_tool_type ett)
Definition editor.c:1341
editor.h
editor_object_type
editor_object_type
Definition editor.h:25
OBJTYPE_PLAYER
@ OBJTYPE_PLAYER
Definition editor.h:30
OBJTYPE_UNIT
@ OBJTYPE_UNIT
Definition editor.h:28
OBJTYPE_STARTPOS
@ OBJTYPE_STARTPOS
Definition editor.h:27
OBJTYPE_GAME
@ OBJTYPE_GAME
Definition editor.h:31
NUM_OBJTYPES
@ NUM_OBJTYPES
Definition editor.h:33
OBJTYPE_CITY
@ OBJTYPE_CITY
Definition editor.h:29
OBJTYPE_TILE
@ OBJTYPE_TILE
Definition editor.h:26
ETT_UNIT
@ ETT_UNIT
Definition editor.h:42
ETT_CITY
@ ETT_CITY
Definition editor.h:43
extra_type_list_by_cause
struct extra_type_list * extra_type_list_by_cause(enum extra_cause cause)
Definition extras.c:241
extra_name_translation
const char * extra_name_translation(const struct extra_type *pextra)
Definition extras.c:186
extra_index
#define extra_index(_e_)
Definition extras.h:177
extra_base_get
#define extra_base_get(_e_)
Definition extras.h:184
extra_road_get
#define extra_road_get(_e_)
Definition extras.h:185
extra_type_by_cause_iterate_end
#define extra_type_by_cause_iterate_end
Definition extras.h:315
extra_type_by_cause_iterate
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:309
free_tokens
void free_tokens(char **tokens, size_t ntokens)
Definition fc_cmdline.c:203
get_tokens
int get_tokens(const char *str, char **tokens, size_t num_tokens, const char *delimiterset)
Definition fc_cmdline.c:166
fc_cmdline.h
fc_funcs
const struct functions * fc_funcs
Definition fc_interface.c:38
fc_interface.h
EC_SPECIAL
#define EC_SPECIAL
Definition fc_types.h:968
fcintl.h
Q_
#define Q_(String)
Definition fcintl.h:70
PL_
#define PL_(String1, String2, n)
Definition fcintl.h:71
_
#define _(String)
Definition fcintl.h:67
game
struct civ_game game
Definition game.c:57
wld
struct world wld
Definition game.c:58
game_unit_by_number
struct unit * game_unit_by_number(int id)
Definition game.c:111
game_city_by_number
struct city * game_city_by_number(int id)
Definition game.c:102
game.h
government_name_translation
const char * government_name_translation(const struct government *pgovern)
Definition government.c:142
government_count
Government_type_id government_count(void)
Definition government.c:70
government_by_number
struct government * government_by_number(const Government_type_id gov)
Definition government.c:102
government_index
Government_type_id government_index(const struct government *pgovern)
Definition government.c:81
government.h
governments_iterate
#define governments_iterate(NAME_pgov)
Definition government.h:120
governments_iterate_end
#define governments_iterate_end
Definition government.h:123
FC_STATIC_CANVAS_INIT
#define FC_STATIC_CANVAS_INIT
Definition canvas.h:27
add_column
static void add_column(GtkWidget *view, int col_id, const char *name, GType gtype, bool editable, bool is_radio, GCallback edit_callback, gpointer callback_userdata)
Definition editprop.c:817
property_page_reset_objbinds
static void property_page_reset_objbinds(struct property_page *pp)
Definition editprop.c:5644
property_page_send_values
static void property_page_send_values(struct property_page *pp)
Definition editprop.c:5488
objprop_setup_widget
static void objprop_setup_widget(struct objprop *op)
Definition editprop.c:2922
property_page_store_creation_tag
static void property_page_store_creation_tag(struct property_page *pp, int tag, int count)
Definition editprop.c:5971
propval_as_string
static gchar * propval_as_string(struct propval *pv)
Definition editprop.c:859
objprop_get_property_page
static struct property_page * objprop_get_property_page(const struct objprop *op)
Definition editprop.c:3430
objprop_get_name
static const char * objprop_get_name(const struct objprop *op)
Definition editprop.c:2802
vision_layer_get_name
const char * vision_layer_get_name(enum vision_layer)
Definition editprop.c:6525
objbind_get_object_id
static int objbind_get_object_id(struct objbind *ob)
Definition editprop.c:1374
objprop_set_extviewer
static void objprop_set_extviewer(struct objprop *op, struct extviewer *ev)
Definition editprop.c:3407
extviewer_get_panel_widget
static GtkWidget * extviewer_get_panel_widget(struct extviewer *ev)
Definition editprop.c:3763
objtype_get_object_from_id
static gpointer objtype_get_object_from_id(enum editor_object_type objtype, int id)
Definition editprop.c:722
property_editor_handle_object_changed
void property_editor_handle_object_changed(struct property_editor *pe, enum editor_object_type objtype, int object_id, bool remove)
Definition editprop.c:6261
propstate_new
static struct propstate * propstate_new(struct objprop *op, struct propval *pv)
Definition editprop.c:1258
valtype_get_name
static const char * valtype_get_name(enum value_types valtype)
Definition editprop.c:776
propstate_destroy
static void propstate_destroy(struct propstate *ps)
Definition editprop.c:1290
objbind_set_modified_value
static bool objbind_set_modified_value(struct objbind *ob, struct objprop *op, struct propval *pv)
Definition editprop.c:2104
objprop_create_cell_renderer
static GtkCellRenderer * objprop_create_cell_renderer(const struct objprop *op)
Definition editprop.c:2826
extviewer_clear_widgets
static void extviewer_clear_widgets(struct extviewer *ev)
Definition editprop.c:4049
value_types
value_types
Definition editprop.c:196
VALTYPE_STRING
@ VALTYPE_STRING
Definition editprop.c:200
VALTYPE_BV_SPECIAL
@ VALTYPE_BV_SPECIAL
Definition editprop.c:204
VALTYPE_BV_BASES
@ VALTYPE_BV_BASES
Definition editprop.c:206
VALTYPE_INT
@ VALTYPE_INT
Definition editprop.c:198
VALTYPE_INVENTIONS_ARRAY
@ VALTYPE_INVENTIONS_ARRAY
Definition editprop.c:203
VALTYPE_BV_ROADS
@ VALTYPE_BV_ROADS
Definition editprop.c:205
VALTYPE_PIXBUF
@ VALTYPE_PIXBUF
Definition editprop.c:201
VALTYPE_TILE_VISION_DATA
@ VALTYPE_TILE_VISION_DATA
Definition editprop.c:210
VALTYPE_NONE
@ VALTYPE_NONE
Definition editprop.c:197
VALTYPE_NATION_HASH
@ VALTYPE_NATION_HASH
Definition editprop.c:208
VALTYPE_BOOL
@ VALTYPE_BOOL
Definition editprop.c:199
VALTYPE_NATION
@ VALTYPE_NATION
Definition editprop.c:207
VALTYPE_GOV
@ VALTYPE_GOV
Definition editprop.c:209
VALTYPE_BUILT_ARRAY
@ VALTYPE_BUILT_ARRAY
Definition editprop.c:202
objprop_set_child_widget
static void objprop_set_child_widget(struct objprop *op, const char *widget_name, GtkWidget *widget)
Definition editprop.c:3347
property_editor_add_page
static bool property_editor_add_page(struct property_editor *pe, enum editor_object_type objtype)
Definition editprop.c:6094
propstate_clear_value
static void propstate_clear_value(struct propstate *ps)
Definition editprop.c:1277
objbind_pack_modified_value
static void objbind_pack_modified_value(struct objbind *ob, struct objprop *op, union packetdata packet)
Definition editprop.c:2356
property_page_get_focused_objbind
static struct objbind * property_page_get_focused_objbind(struct property_page *pp)
Definition editprop.c:5375
objprop_has_widget
static bool objprop_has_widget(const struct objprop *op)
Definition editprop.c:2715
objtype_get_id_from_object
static int objtype_get_id_from_object(enum editor_object_type objtype, gpointer object)
Definition editprop.c:693
objbind_get_objtype
static enum editor_object_type objbind_get_objtype(const struct objbind *ob)
Definition editprop.c:2188
objprop_get_extviewer
static struct extviewer * objprop_get_extviewer(struct objprop *op)
Definition editprop.c:3419
extviewer_refresh_widgets
static void extviewer_refresh_widgets(struct extviewer *ev, struct propval *pv)
Definition editprop.c:3786
property_page_get_objtype
static enum editor_object_type property_page_get_objtype(const struct property_page *pp)
Definition editprop.c:5030
property_page_objbind_iterate_end
#define property_page_objbind_iterate_end
Definition editprop.c:638
property_page_show_extviewer
static void property_page_show_extviewer(struct property_page *pp, struct extviewer *ev)
Definition editprop.c:5946
objbind_get_object
static gpointer objbind_get_object(struct objbind *ob)
Definition editprop.c:1358
property_page_get_name
static const char * property_page_get_name(const struct property_page *pp)
Definition editprop.c:5018
property_editor_handle_object_created
void property_editor_handle_object_created(struct property_editor *pe, int tag, int object_id)
Definition editprop.c:6283
objbind_property_is_modified
static bool objbind_property_is_modified(struct objbind *ob, struct objprop *op)
Definition editprop.c:2059
propstate_get_value
static struct propval * propstate_get_value(struct propstate *ps)
Definition editprop.c:1320
property_page_clear_tags
static void property_page_clear_tags(struct property_page *pp)
Definition editprop.c:6023
property_page_object_created
static void property_page_object_created(struct property_page *pp, int tag, int object_id)
Definition editprop.c:5900
property_page_tag_is_known
static bool property_page_tag_is_known(struct property_page *pp, int tag)
Definition editprop.c:6012
property_page_remove_creation_tag
static void property_page_remove_creation_tag(struct property_page *pp, int tag)
Definition editprop.c:5993
property_page_load_tiles
static void property_page_load_tiles(struct property_page *pp, const struct tile_list *tiles)
Definition editprop.c:5417
property_page_create_objects
static void property_page_create_objects(struct property_page *pp, struct tile_list *hint_tiles)
Definition editprop.c:5724
property_page_add_extviewer
static void property_page_add_extviewer(struct property_page *pp, struct extviewer *ev)
Definition editprop.c:5926
property_page_refresh_button_clicked
static void property_page_refresh_button_clicked(GtkButton *button, gpointer userdata)
Definition editprop.c:6045
property_page_set_focused_objbind
static void property_page_set_focused_objbind(struct property_page *pp, struct objbind *ob)
Definition editprop.c:5387
property_page_setup_objprops
static void property_page_setup_objprops(struct property_page *pp)
Definition editprop.c:4388
objbind_set_rowref
static void objbind_set_rowref(struct objbind *ob, GtkTreeRowReference *rr)
Definition editprop.c:2622
object_property_flags
object_property_flags
Definition editprop.c:381
OPF_IN_LISTVIEW
@ OPF_IN_LISTVIEW
Definition editprop.c:384
OPF_EDITABLE
@ OPF_EDITABLE
Definition editprop.c:383
OPF_HAS_WIDGET
@ OPF_HAS_WIDGET
Definition editprop.c:385
OPF_NO_FLAGS
@ OPF_NO_FLAGS
Definition editprop.c:382
objbind_clear_modified_value
static void objbind_clear_modified_value(struct objbind *ob, struct objprop *op)
Definition editprop.c:2045
objbind_get_value_from_object
static struct propval * objbind_get_value_from_object(struct objbind *ob, struct objprop *op)
Definition editprop.c:1435
propval_free
static void propval_free(struct propval *pv)
Definition editprop.c:1120
property_filter_new
static struct property_filter * property_filter_new(const char *filter)
Definition editprop.c:6369
property_page_set_store_value
static bool property_page_set_store_value(struct property_page *pp, struct objprop *op, struct objbind *ob, GtkTreeIter *iter)
Definition editprop.c:5231
objtype_get_name
static const char * objtype_get_name(enum editor_object_type objtype)
Definition editprop.c:664
objprop_widget_entry_changed
static void objprop_widget_entry_changed(GtkEntry *entry, gpointer userdata)
Definition editprop.c:2872
objbind_clear_all_modified_values
static void objbind_clear_all_modified_values(struct objbind *ob)
Definition editprop.c:2090
property_filter_match
static bool property_filter_match(struct property_filter *pf, const struct objprop *op)
Definition editprop.c:6443
property_editor_popup
void property_editor_popup(struct property_editor *pe, enum editor_object_type objtype)
Definition editprop.c:6231
property_page_destroy_button_clicked
static void property_page_destroy_button_clicked(GtkButton *button, gpointer userdata)
Definition editprop.c:6083
objbind_new
static struct objbind * objbind_new(enum editor_object_type objtype, gpointer object)
Definition editprop.c:1332
property_page_selection_func
static gboolean property_page_selection_func(GtkTreeSelection *sel, GtkTreeModel *model, GtkTreePath *path, gboolean currently_selected, gpointer data)
Definition editprop.c:4614
property_page_get_num_objbinds
static int property_page_get_num_objbinds(const struct property_page *pp)
Definition editprop.c:5434
objprop_show_in_listview
static bool objprop_show_in_listview(const struct objprop *op)
Definition editprop.c:2704
objprop_get_gtype
static GType objprop_get_gtype(const struct objprop *op)
Definition editprop.c:2660
objprop_set_treeview_column
static void objprop_set_treeview_column(struct objprop *op, GtkTreeViewColumn *col)
Definition editprop.c:2778
objbind_pack_current_values
static void objbind_pack_current_values(struct objbind *ob, union packetdata packet)
Definition editprop.c:2213
objprop_get_attribute_type_string
static const char * objprop_get_attribute_type_string(const struct objprop *op)
Definition editprop.c:2729
propval_copy
static struct propval * propval_copy(struct propval *pv)
Definition editprop.c:1038
editprop_get_property_editor
struct property_editor * editprop_get_property_editor(void)
Definition editprop.c:6184
property_editor_reload
void property_editor_reload(struct property_editor *pe, enum editor_object_type objtype)
Definition editprop.c:6321
create_unit_pixbuf
static GdkPixbuf * create_unit_pixbuf(const struct unit *punit)
Definition editprop.c:5058
extviewer_view_cell_toggled
static void extviewer_view_cell_toggled(GtkCellRendererToggle *cell, gchar *path, gpointer userdata)
Definition editprop.c:4124
property_editor_new
static struct property_editor * property_editor_new(void)
Definition editprop.c:6141
property_page_send_packet
static void property_page_send_packet(struct property_page *pp, union packetdata packet)
Definition editprop.c:5583
built_status_to_string
static gchar * built_status_to_string(struct built_status *bs)
Definition editprop.c:974
objprop_get_id
static int objprop_get_id(const struct objprop *op)
Definition editprop.c:2645
object_property_ids
object_property_ids
Definition editprop.c:304
OPID_STARTPOS_IMAGE
@ OPID_STARTPOS_IMAGE
Definition editprop.c:324
OPID_TILE_Y
@ OPID_TILE_Y
Definition editprop.c:307
OPID_TILE_BASES
@ OPID_TILE_BASES
Definition editprop.c:320
OPID_CITY_XY
@ OPID_CITY_XY
Definition editprop.c:350
OPID_UNIT_ID
@ OPID_UNIT_ID
Definition editprop.c:334
OPID_CITY_BUILDINGS
@ OPID_CITY_BUILDINGS
Definition editprop.c:353
OPID_CITY_NAME
@ OPID_CITY_NAME
Definition editprop.c:345
OPID_TILE_NAT_Y
@ OPID_TILE_NAT_Y
Definition editprop.c:309
OPID_CITY_SIZE
@ OPID_CITY_SIZE
Definition editprop.c:351
OPID_UNIT_VETERAN
@ OPID_UNIT_VETERAN
Definition editprop.c:341
OPID_CITY_IMAGE
@ OPID_CITY_IMAGE
Definition editprop.c:344
OPID_CITY_SHIELD_STOCK
@ OPID_CITY_SHIELD_STOCK
Definition editprop.c:355
OPID_PLAYER_NAME
@ OPID_PLAYER_NAME
Definition editprop.c:357
OPID_PLAYER_AGE
@ OPID_PLAYER_AGE
Definition editprop.c:360
OPID_STARTPOS_NATIONS
@ OPID_STARTPOS_NATIONS
Definition editprop.c:327
OPID_GAME_LAKE_FLOODING
@ OPID_GAME_LAKE_FLOODING
Definition editprop.c:377
OPID_UNIT_IMAGE
@ OPID_UNIT_IMAGE
Definition editprop.c:329
OPID_TILE_TERRAIN
@ OPID_TILE_TERRAIN
Definition editprop.c:314
OPID_TILE_SPECIALS
@ OPID_TILE_SPECIALS
Definition editprop.c:318
OPID_TILE_RESOURCE
@ OPID_TILE_RESOURCE
Definition editprop.c:317
OPID_TILE_IMAGE
@ OPID_TILE_IMAGE
Definition editprop.c:305
OPID_TILE_VISION
@ OPID_TILE_VISION
Definition editprop.c:321
OPID_PLAYER_INVENTIONS
@ OPID_PLAYER_INVENTIONS
Definition editprop.c:364
OPID_GAME_SCENARIO_NAME
@ OPID_GAME_SCENARIO_NAME
Definition editprop.c:370
OPID_PLAYER_SCIENCE
@ OPID_PLAYER_SCIENCE
Definition editprop.c:366
OPID_TILE_CONTINENT
@ OPID_TILE_CONTINENT
Definition editprop.c:310
OPID_CITY_HISTORY
@ OPID_CITY_HISTORY
Definition editprop.c:352
OPID_TILE_XY
@ OPID_TILE_XY
Definition editprop.c:316
OPID_GAME_SCENARIO_AUTHORS
@ OPID_GAME_SCENARIO_AUTHORS
Definition editprop.c:371
OPID_TILE_X
@ OPID_TILE_X
Definition editprop.c:306
OPID_TILE_NAT_X
@ OPID_TILE_NAT_X
Definition editprop.c:308
OPID_PLAYER_NATION
@ OPID_PLAYER_NATION
Definition editprop.c:358
OPID_GAME_PREVENT_CITIES
@ OPID_GAME_PREVENT_CITIES
Definition editprop.c:376
OPID_STARTPOS_XY
@ OPID_STARTPOS_XY
Definition editprop.c:325
OPID_UNIT_MOVED
@ OPID_UNIT_MOVED
Definition editprop.c:338
OPID_TILE_LABEL
@ OPID_TILE_LABEL
Definition editprop.c:322
OPID_CITY_FOOD_STOCK
@ OPID_CITY_FOOD_STOCK
Definition editprop.c:354
OPID_UNIT_DONE_MOVING
@ OPID_UNIT_DONE_MOVING
Definition editprop.c:339
OPID_UNIT_MOVES_LEFT
@ OPID_UNIT_MOVES_LEFT
Definition editprop.c:336
OPID_GAME_SCENARIO_DESC
@ OPID_GAME_SCENARIO_DESC
Definition editprop.c:372
OPID_GAME_STARTPOS_NATIONS
@ OPID_GAME_STARTPOS_NATIONS
Definition editprop.c:375
OPID_UNIT_HP
@ OPID_UNIT_HP
Definition editprop.c:340
OPID_UNIT_FUEL
@ OPID_UNIT_FUEL
Definition editprop.c:337
OPID_PLAYER_SCENARIO_RESERVED
@ OPID_PLAYER_SCENARIO_RESERVED
Definition editprop.c:365
OPID_TILE_ROADS
@ OPID_TILE_ROADS
Definition editprop.c:319
OPID_PLAYER_GOLD
@ OPID_PLAYER_GOLD
Definition editprop.c:367
OPID_CITY_ID
@ OPID_CITY_ID
Definition editprop.c:349
OPID_GAME_SCENARIO_RANDSTATE
@ OPID_GAME_SCENARIO_RANDSTATE
Definition editprop.c:373
OPID_GAME_SCENARIO_PLAYERS
@ OPID_GAME_SCENARIO_PLAYERS
Definition editprop.c:374
OPID_UNIT_STAY
@ OPID_UNIT_STAY
Definition editprop.c:342
OPID_PLAYER_GOV
@ OPID_PLAYER_GOV
Definition editprop.c:359
OPID_STARTPOS_EXCLUDE
@ OPID_STARTPOS_EXCLUDE
Definition editprop.c:326
OPID_UNIT_TYPE
@ OPID_UNIT_TYPE
Definition editprop.c:333
OPID_GAME_SCENARIO
@ OPID_GAME_SCENARIO
Definition editprop.c:369
OPID_GAME_RULESET_LOCKED
@ OPID_GAME_RULESET_LOCKED
Definition editprop.c:378
OPID_UNIT_XY
@ OPID_UNIT_XY
Definition editprop.c:335
OPID_TILE_INDEX
@ OPID_TILE_INDEX
Definition editprop.c:315
objprop_get_valtype
static enum value_types objprop_get_valtype(const struct objprop *op)
Definition editprop.c:2693
get_next_unique_tag
static int get_next_unique_tag(void)
Definition editprop.c:1027
objprop_is_sortable
static bool objprop_is_sortable(const struct objprop *op)
Definition editprop.c:2847
property_page_add_objbinds_from_tile
static void property_page_add_objbinds_from_tile(struct property_page *pp, const struct tile *ptile)
Definition editprop.c:5177
objprop_get_tooltip
static const char * objprop_get_tooltip(const struct objprop *op)
Definition editprop.c:2813
objbind_get_rowref
static GtkTreeRowReference * objbind_get_rowref(struct objbind *ob)
Definition editprop.c:2634
property_filter_free
static void property_filter_free(struct property_filter *pf)
Definition editprop.c:6497
objprop_widget_spin_button_changed
static void objprop_widget_spin_button_changed(GtkSpinButton *spin, gpointer userdata)
Definition editprop.c:2888
PF_DISJUNCTION_SEPARATOR
#define PF_DISJUNCTION_SEPARATOR
Definition editprop.c:118
objprop_get_child_widget
static GtkWidget * objprop_get_child_widget(struct objprop *op, const char *widget_name)
Definition editprop.c:3374
property_page_selection_changed
static void property_page_selection_changed(GtkTreeSelection *sel, gpointer userdata)
Definition editprop.c:4589
objtype_is_conserved
static bool objtype_is_conserved(enum editor_object_type objtype)
Definition editprop.c:753
extviewer_new
static struct extviewer * extviewer_new(struct objprop *op)
Definition editprop.c:3466
propval_equal
static bool propval_equal(struct propval *pva, struct propval *pvb)
Definition editprop.c:1171
property_page_quick_find_entry_changed
static void property_page_quick_find_entry_changed(GtkWidget *entry, gpointer userdata)
Definition editprop.c:4669
objprop_refresh_widget
static void objprop_refresh_widget(struct objprop *op, struct objbind *ob)
Definition editprop.c:3098
PF_MAX_CLAUSES
#define PF_MAX_CLAUSES
Definition editprop.c:117
property_editor_popdown
void property_editor_popdown(struct property_editor *pe)
Definition editprop.c:6249
objbind_destroy
static void objbind_destroy(struct objbind *ob)
Definition editprop.c:2169
property_page_add_objbind
static void property_page_add_objbind(struct property_page *pp, gpointer object_data)
Definition editprop.c:5141
objbind_request_destroy_object
static void objbind_request_destroy_object(struct objbind *ob)
Definition editprop.c:1387
property_page_create_button_clicked
static void property_page_create_button_clicked(GtkButton *button, gpointer userdata)
Definition editprop.c:6055
create_pixbuf_from_layers
static GdkPixbuf * create_pixbuf_from_layers(const struct tile *ptile, const struct unit *punit, const struct city *pcity, enum layer_category category)
Definition editprop.c:5084
property_page_new_packet
static union packetdata property_page_new_packet(struct property_page *pp)
Definition editprop.c:5542
propstate_set_value
static void propstate_set_value(struct propstate *ps, struct propval *pv)
Definition editprop.c:1305
objprop_get_column_id
static int objprop_get_column_id(const struct objprop *op)
Definition editprop.c:2767
create_tile_pixbuf
static GdkPixbuf * create_tile_pixbuf(const struct tile *ptile)
Definition editprop.c:5046
extviewer_get_objprop
static struct objprop * extviewer_get_objprop(struct extviewer *ev)
Definition editprop.c:3751
can_create_unit_at_tile
static bool can_create_unit_at_tile(struct tile *ptile)
Definition editprop.c:995
property_page_get_objbind
static struct objbind * property_page_get_objbind(struct property_page *pp, int object_id)
Definition editprop.c:5400
objbind_get_allowed_value_span
static bool objbind_get_allowed_value_span(struct objbind *ob, struct objprop *op, double *pmin, double *pmax, double *pstep, double *pbig_step)
Definition editprop.c:1870
property_page_free_packet
static void property_page_free_packet(struct property_page *pp, union packetdata packet)
Definition editprop.c:5624
create_city_pixbuf
static GdkPixbuf * create_city_pixbuf(const struct city *pcity)
Definition editprop.c:5070
ADDPROP
#define ADDPROP(ARG_id, ARG_name, ARG_tooltip, ARG_flags, ARG_valtype)
extviewer_panel_button_clicked
static void extviewer_panel_button_clicked(GtkButton *button, gpointer userdata)
Definition editprop.c:4104
property_page_destroy_objects
static void property_page_destroy_objects(struct property_page *pp)
Definition editprop.c:5685
property_editor_load_tiles
void property_editor_load_tiles(struct property_editor *pe, const struct tile_list *tiles)
Definition editprop.c:6195
property_page_new
static struct property_page * property_page_new(enum editor_object_type objtype, struct property_editor *parent)
Definition editprop.c:4711
property_page_objprop_iterate_end
#define property_page_objprop_iterate_end
Definition editprop.c:634
property_page_clear_objbinds
static void property_page_clear_objbinds(struct property_page *pp)
Definition editprop.c:5126
property_editor_clear
void property_editor_clear(struct property_editor *pe)
Definition editprop.c:6301
property_page_objprop_iterate
#define property_page_objprop_iterate(ARG_pp, NAME_op)
Definition editprop.c:632
objprop_set_column_id
static void objprop_set_column_id(struct objprop *op, int col_id)
Definition editprop.c:2754
objbind_bind_properties
static void objbind_bind_properties(struct objbind *ob, struct property_page *pp)
Definition editprop.c:2199
property_page_fill_widgets
static void property_page_fill_widgets(struct property_page *pp)
Definition editprop.c:5326
objbind_has_modified_properties
static bool objbind_has_modified_properties(struct objbind *ob)
Definition editprop.c:2078
property_page_change_value
static void property_page_change_value(struct property_page *pp, struct objprop *op, struct propval *pv)
Definition editprop.c:5446
objprop_widget_toggle_button_changed
static void objprop_widget_toggle_button_changed(GtkToggleButton *button, gpointer userdata)
Definition editprop.c:2905
PF_CONJUNCTION_SEPARATOR
#define PF_CONJUNCTION_SEPARATOR
Definition editprop.c:119
property_page_apply_button_clicked
static void property_page_apply_button_clicked(GtkButton *button, gpointer userdata)
Definition editprop.c:6034
objprop_new
static struct objprop * objprop_new(int id, const char *name, const char *tooltip, enum object_property_flags flags, enum value_types valtype, struct property_page *parent)
Definition editprop.c:3441
extviewer_get_view_widget
static GtkWidget * extviewer_get_view_widget(struct extviewer *ev)
Definition editprop.c:3775
objprop_get_widget
static GtkWidget * objprop_get_widget(struct objprop *op)
Definition editprop.c:3332
propval_free_data
static void propval_free_data(struct propval *pv)
Definition editprop.c:1134
extviewer_textbuf_changed
static void extviewer_textbuf_changed(GtkTextBuffer *textbuf, gpointer userdata)
Definition editprop.c:4339
the_property_editor
static struct property_editor * the_property_editor
Definition editprop.c:658
property_page_object_changed
static void property_page_object_changed(struct property_page *pp, int object_id, bool remove)
Definition editprop.c:5848
objprop_is_readonly
static bool objprop_is_readonly(const struct objprop *op)
Definition editprop.c:2861
property_page_objbind_iterate
#define property_page_objbind_iterate(ARG_pp, NAME_ob)
Definition editprop.c:636
objprop_get_treeview_column
static GtkTreeViewColumn * objprop_get_treeview_column(const struct objprop *op)
Definition editprop.c:2791
property_editor_get_page
static struct property_page * property_editor_get_page(struct property_editor *pe, enum editor_object_type objtype)
Definition editprop.c:6128
objbind_get_modified_value
static struct propval * objbind_get_modified_value(struct objbind *ob, struct objprop *op)
Definition editprop.c:2150
toplevel
GtkWidget * toplevel
Definition gui_main.c:124
disable_gobject_callback
void disable_gobject_callback(GObject *obj, GCallback cb)
Definition gui_stuff.c:1087
enable_gobject_callback
void enable_gobject_callback(GObject *obj, GCallback cb)
Definition gui_stuff.c:1103
get_flag
GdkPixbuf * get_flag(const struct nation_type *nation)
Definition plrdlg.c:609
tooltip
const char * tooltip
Definition repodlgs.c:1314
title
const char * title
Definition repodlgs.c:1313
surface_get_pixbuf
GdkPixbuf * surface_get_pixbuf(cairo_surface_t *surf, int width, int height)
Definition sprite.c:418
sprite_get_pixbuf
GdkPixbuf * sprite_get_pixbuf(struct sprite *sprite)
Definition sprite.c:402
value_types
value_types
Definition editprop.c:196
object_property_flags
object_property_flags
Definition editprop.c:381
PF_MAX_CLAUSES
#define PF_MAX_CLAUSES
Definition editprop.c:117
editprop.h
gui_stuff.h
canvas.h
gui_main.h
plrdlg.h
sprite.h
is_special_improvement
bool is_special_improvement(const struct impr_type *pimprove)
Definition improvement.c:792
improvement_index
Impr_type_id improvement_index(const struct impr_type *pimprove)
Definition improvement.c:173
is_great_wonder
bool is_great_wonder(const struct impr_type *pimprove)
Definition improvement.c:767
improvement_name_translation
const char * improvement_name_translation(const struct impr_type *pimprove)
Definition improvement.c:241
is_small_wonder
bool is_small_wonder(const struct impr_type *pimprove)
Definition improvement.c:775
improvement_iterate_end
#define improvement_iterate_end
Definition improvement.h:211
improvement_iterate
#define improvement_iterate(_p)
Definition improvement.h:205
B_LAST
#define B_LAST
Definition improvement.h:42
name
const char * name
Definition inputfile.c:127
log.h
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
log_error
#define log_error(message,...)
Definition log.h:103
map_startpos_get
struct startpos * map_startpos_get(const struct tile *ptile)
Definition map.c:1686
startpos_number
int startpos_number(const struct startpos *psp)
Definition map.c:1436
nat_x
#define nat_x
nat_y
#define nat_y
startpos_tile
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1479
startpos_raw_nations
const struct nation_hash * startpos_raw_nations(const struct startpos *psp)
Definition map.c:1568
startpos_pack
bool startpos_pack(const struct startpos *psp, struct packet_edit_startpos_full *packet)
Definition map.c:1509
index_to_tile
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:454
startpos_is_excluding
bool startpos_is_excluding(const struct startpos *psp)
Definition map.c:1556
map_startpos_by_number
struct startpos * map_startpos_by_number(int id)
Definition map.c:1427
map.h
index_to_native_pos
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition map.h:151
index_to_map_pos
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition map.h:227
get_center_tile_mapcanvas
struct tile * get_center_tile_mapcanvas(void)
Definition mapview_common.c:1212
put_one_element
void put_one_element(struct canvas *pcanvas, float zoom, enum mapview_layer layer, const struct tile *ptile, const struct tile_edge *pedge, const struct tile_corner *pcorner, const struct unit *punit, const struct city *pcity, int canvas_x, int canvas_y, const struct city *citymode, const struct unit_type *putype)
Definition mapview_common.c:1349
mapview_common.h
mem.h
fc_calloc
#define fc_calloc(n, esz)
Definition mem.h:38
fc_strdup
#define fc_strdup(str)
Definition mem.h:43
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
can_unit_exist_at_tile
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:304
movement.h
MAX_MOVE_FRAGS
#define MAX_MOVE_FRAGS
Definition movement.h:27
nation_count
Nation_type_id nation_count(void)
Definition nation.c:506
nation_number
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:485
nation_adjective_translation
const char * nation_adjective_translation(const struct nation_type *pnation)
Definition nation.c:148
nation_by_number
struct nation_type * nation_by_number(const Nation_type_id nation)
Definition nation.c:474
nation_of_player
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:443
is_nation_playable
bool is_nation_playable(const struct nation_type *nation)
Definition nation.c:199
nation_index
Nation_type_id nation_index(const struct nation_type *pnation)
Definition nation.c:497
nation_barbarian_type
enum barbarian_type nation_barbarian_type(const struct nation_type *nation)
Definition nation.c:210
nation_hash_iterate
#define nation_hash_iterate(nationhash, pnation)
Definition nation.h:92
nations_iterate_end
#define nations_iterate_end
Definition nation.h:335
nations_iterate
#define nations_iterate(NAME_pnation)
Definition nation.h:332
nation_hash_iterate_end
#define nation_hash_iterate_end
Definition nation.h:94
dsend_packet_edit_city_create
int dsend_packet_edit_city_create(struct connection *pc, int owner, int tile, int size, int tag)
Definition packets_gen.c:88804
send_packet_edit_city
int send_packet_edit_city(struct connection *pc, const struct packet_edit_city *packet)
Definition packets_gen.c:92349
send_packet_edit_game
int send_packet_edit_game(struct connection *pc, const struct packet_edit_game *packet)
Definition packets_gen.c:94257
dsend_packet_edit_city_remove
int dsend_packet_edit_city_remove(struct connection *pc, int id16, int id32)
Definition packets_gen.c:89112
dsend_packet_edit_unit_remove_by_id
int dsend_packet_edit_unit_remove_by_id(struct connection *pc, int id16, int id32)
Definition packets_gen.c:87344
send_packet_edit_startpos_full
int send_packet_edit_startpos_full(struct connection *pc, const struct packet_edit_startpos_full *packet)
Definition packets_gen.c:86091
dsend_packet_edit_startpos
int dsend_packet_edit_startpos(struct connection *pc, int id, bool removal, int tag)
Definition packets_gen.c:86012
send_packet_edit_player
int send_packet_edit_player(struct connection *pc, const struct packet_edit_player *packet)
Definition packets_gen.c:93709
dsend_packet_edit_player_create
int dsend_packet_edit_player_create(struct connection *pc, int tag)
Definition packets_gen.c:92515
send_packet_edit_unit
int send_packet_edit_unit(struct connection *pc, const struct packet_edit_unit *packet)
Definition packets_gen.c:88545
send_packet_edit_scenario_desc
int send_packet_edit_scenario_desc(struct connection *pc, const struct packet_edit_scenario_desc *packet)
Definition packets_gen.c:94411
dsend_packet_edit_unit_create
int dsend_packet_edit_unit_create(struct connection *pc, int owner, int tile, Unit_type_id type, int count, int tag)
Definition packets_gen.c:86766
dsend_packet_edit_player_remove
int dsend_packet_edit_player_remove(struct connection *pc, int id)
Definition packets_gen.c:92678
send_packet_edit_tile
int send_packet_edit_tile(struct connection *pc, const struct packet_edit_tile *packet)
Definition packets_gen.c:86466
player_slot_is_used
bool player_slot_is_used(const struct player_slot *pslot)
Definition player.c:441
player_by_number
struct player * player_by_number(const int player_id)
Definition player.c:840
player_number
int player_number(const struct player *pplayer)
Definition player.c:828
player_name
const char * player_name(const struct player *pplayer)
Definition player.c:886
player_slot_index
int player_slot_index(const struct player_slot *pslot)
Definition player.c:419
player_has_flag
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1954
player_index
int player_index(const struct player *pplayer)
Definition player.c:820
pplayers_allied
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1381
player_slot_get_player
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:430
players_iterate_end
#define players_iterate_end
Definition player.h:535
players_iterate
#define players_iterate(_pplayer)
Definition player.h:530
player_slots_iterate
#define player_slots_iterate(_pslot)
Definition player.h:521
player_slots_iterate_end
#define player_slots_iterate_end
Definition player.h:525
research_get
struct research * research_get(const struct player *pplayer)
Definition research.c:126
research_invention_state
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:616
research.h
road_count
Road_type_id road_count(void)
Definition road.c:50
road_number
Road_type_id road_number(const struct road_type *proad)
Definition road.c:32
ARRAY_SIZE
#define ARRAY_SIZE(x)
Definition shared.h:85
spechash.h
step
int step
Definition specpq.h:92
size
size_t size
Definition specvec.h:72
base_type
Definition base.h:41
built_status
Definition city.h:237
built_status::turn
int turn
Definition city.h:238
canvas
Definition canvas.h:21
canvas::surface
cairo_surface_t * surface
Definition canvas.h:22
city
Definition city.h:309
city::food_stock
int food_stock
Definition city.h:354
city::built
struct built_status built[B_LAST]
Definition city.h:380
city::history
int history
Definition city.h:393
city::id
int id
Definition city.h:315
city::name
char * name
Definition city.h:310
city::shield_stock
int shield_stock
Definition city.h:355
civ_game
Definition game.h:82
civ_game::scenario_desc
struct packet_scenario_description scenario_desc
Definition game.h:88
civ_game::info
struct packet_game_info info
Definition game.h:89
civ_game::scenario
struct packet_scenario_info scenario
Definition game.h:87
civclient::conn
struct connection conn
Definition client_main.h:96
connection
Definition connection.h:141
entry
Definition registry_ini.c:193
extra_type
Definition extras.h:85
extviewer
Definition editprop.c:511
extviewer::view_widget
GtkWidget * view_widget
Definition editprop.c:520
extviewer::panel_button
GtkWidget * panel_button
Definition editprop.c:517
extviewer::view_label
GtkWidget * view_label
Definition editprop.c:521
extviewer::panel_image
GtkWidget * panel_image
Definition editprop.c:518
extviewer::textbuf
GtkTextBuffer * textbuf
Definition editprop.c:524
extviewer::objprop
struct objprop * objprop
Definition editprop.c:512
extviewer::panel_label
GtkWidget * panel_label
Definition editprop.c:516
extviewer::pv_cached
struct propval * pv_cached
Definition editprop.c:513
extviewer::store
GtkListStore * store
Definition editprop.c:523
extviewer::panel_widget
GtkWidget * panel_widget
Definition editprop.c:515
functions::player_tile_vision_get
bool(* player_tile_vision_get)(const struct tile *ptile, const struct player *pplayer, enum vision_layer vision)
Definition fc_interface.h:46
government
Definition government.h:52
nation_type
Definition nation.h:97
objbind
Definition editprop.c:455
objbind::object_id
int object_id
Definition editprop.c:457
objbind::propstate_table
struct propstate_hash * propstate_table
Definition editprop.c:459
objbind::parent_property_page
struct property_page * parent_property_page
Definition editprop.c:458
objbind::rowref
GtkTreeRowReference * rowref
Definition editprop.c:460
objbind::objtype
enum editor_object_type objtype
Definition editprop.c:456
objprop
Definition editprop.c:388
objprop::name
const char * name
Definition editprop.c:390
objprop::tooltip
const char * tooltip
Definition editprop.c:391
objprop::widget
GtkWidget * widget
Definition editprop.c:396
objprop::parent_page
struct property_page * parent_page
Definition editprop.c:398
objprop::flags
enum object_property_flags flags
Definition editprop.c:392
objprop::extviewer
struct extviewer * extviewer
Definition editprop.c:397
objprop::id
int id
Definition editprop.c:389
objprop::valtype
enum value_types valtype
Definition editprop.c:393
objprop::column_id
int column_id
Definition editprop.c:394
objprop::view_column
GtkTreeViewColumn * view_column
Definition editprop.c:395
packet_edit_city
Definition packets_gen.h:1766
packet_edit_city::shield_stock
int shield_stock
Definition packets_gen.h:1781
packet_edit_city::built
int built[B_LAST]
Definition packets_gen.h:1792
packet_edit_city::name
char name[MAX_LEN_CITYNAME]
Definition packets_gen.h:1769
packet_edit_city::history
int history
Definition packets_gen.h:1773
packet_edit_city::food_stock
int food_stock
Definition packets_gen.h:1780
packet_edit_city::id16
int id16
Definition packets_gen.h:1767
packet_edit_city::id32
int id32
Definition packets_gen.h:1768
packet_edit_city::size
int size
Definition packets_gen.h:1772
packet_edit_game
Definition packets_gen.h:1841
packet_edit_game::ruleset_locked
bool ruleset_locked
Definition packets_gen.h:1850
packet_edit_game::scenario_players
bool scenario_players
Definition packets_gen.h:1846
packet_edit_game::lake_flooding
bool lake_flooding
Definition packets_gen.h:1849
packet_edit_game::startpos_nations
bool startpos_nations
Definition packets_gen.h:1847
packet_edit_game::scenario_name
char scenario_name[256]
Definition packets_gen.h:1843
packet_edit_game::prevent_new_cities
bool prevent_new_cities
Definition packets_gen.h:1848
packet_edit_game::scenario
bool scenario
Definition packets_gen.h:1842
packet_edit_game::scenario_authors
char scenario_authors[MAX_LEN_PACKET/3]
Definition packets_gen.h:1844
packet_edit_game::scenario_random
bool scenario_random
Definition packets_gen.h:1845
packet_edit_player
Definition packets_gen.h:1806
packet_edit_player::gold
int gold
Definition packets_gen.h:1822
packet_edit_player::scenario_reserved
bool scenario_reserved
Definition packets_gen.h:1831
packet_edit_player::nation
Nation_type_id nation
Definition packets_gen.h:1815
packet_edit_player::name
char name[MAX_LEN_NAME]
Definition packets_gen.h:1808
packet_edit_player::id
int id
Definition packets_gen.h:1807
packet_edit_player::government
Government_type_id government
Definition packets_gen.h:1813
packet_edit_player::inventions
bool inventions[A_LAST+1]
Definition packets_gen.h:1829
packet_edit_player::bulbs_researched
int bulbs_researched
Definition packets_gen.h:1828
packet_edit_scenario_desc
Definition packets_gen.h:1853
packet_edit_startpos_full
Definition packets_gen.h:1695
packet_edit_startpos_full::exclude
bool exclude
Definition packets_gen.h:1697
packet_edit_startpos_full::nations
bv_startpos_nations nations
Definition packets_gen.h:1698
packet_edit_tile
Definition packets_gen.h:1701
packet_edit_tile::label
char label[MAX_LEN_NAME]
Definition packets_gen.h:1708
packet_edit_tile::extras
bv_extras extras
Definition packets_gen.h:1703
packet_edit_tile::tile
int tile
Definition packets_gen.h:1702
packet_edit_unit
Definition packets_gen.h:1731
packet_edit_unit::stay
bool stay
Definition packets_gen.h:1751
packet_edit_unit::moved
bool moved
Definition packets_gen.h:1746
packet_edit_unit::done_moving
bool done_moving
Definition packets_gen.h:1748
packet_edit_unit::id16
int id16
Definition packets_gen.h:1732
packet_edit_unit::moves_left
int moves_left
Definition packets_gen.h:1738
packet_edit_unit::id32
int id32
Definition packets_gen.h:1733
packet_edit_unit::hp
int hp
Definition packets_gen.h:1739
packet_edit_unit::fuel
int fuel
Definition packets_gen.h:1741
packet_edit_unit::veteran
int veteran
Definition packets_gen.h:1740
packet_game_info::turn
int turn
Definition packets_gen.h:241
packet_scenario_description::description
char description[MAX_LEN_CONTENT]
Definition packets_gen.h:1622
packet_scenario_info::lake_flooding
bool lake_flooding
Definition packets_gen.h:1612
packet_scenario_info::is_scenario
bool is_scenario
Definition packets_gen.h:1605
packet_scenario_info::ruleset_locked
bool ruleset_locked
Definition packets_gen.h:1615
packet_scenario_info::players
bool players
Definition packets_gen.h:1608
packet_scenario_info::authors
char authors[MAX_LEN_PACKET/3]
Definition packets_gen.h:1607
packet_scenario_info::name
char name[256]
Definition packets_gen.h:1606
packet_scenario_info::prevent_new_cities
bool prevent_new_cities
Definition packets_gen.h:1611
packet_scenario_info::startpos_nations
bool startpos_nations
Definition packets_gen.h:1609
packet_scenario_info::save_random
bool save_random
Definition packets_gen.h:1610
pf_conjunction
Definition editprop.c:126
pf_conjunction::conjunction
struct pf_pattern conjunction[PF_MAX_CLAUSES]
Definition editprop.c:127
pf_conjunction::count
int count
Definition editprop.c:128
pf_pattern
Definition editprop.c:121
pf_pattern::text
char * text
Definition editprop.c:123
pf_pattern::negate
bool negate
Definition editprop.c:122
player_economic::gold
int gold
Definition player.h:70
player
Definition player.h:249
player::government
struct government * government
Definition player.h:258
player::turns_alive
int turns_alive
Definition player.h:266
player::economic
struct player_economic economic
Definition player.h:284
player::name
char name[MAX_LEN_NAME]
Definition player.h:251
player::nation
struct nation_type * nation
Definition player.h:260
property_editor
Definition editprop.c:644
property_editor::notebook
GtkWidget * notebook
Definition editprop.c:646
property_editor::property_pages
struct property_page * property_pages[NUM_OBJTYPES]
Definition editprop.c:648
property_editor::widget
GtkWidget * widget
Definition editprop.c:645
property_filter
Definition editprop.c:131
property_filter::count
int count
Definition editprop.c:133
property_filter::disjunction
struct pf_conjunction disjunction[PF_MAX_CLAUSES]
Definition editprop.c:132
property_page
Definition editprop.c:546
property_page::object_store
GtkListStore * object_store
Definition editprop.c:550
property_page::pe_parent
struct property_editor * pe_parent
Definition editprop.c:554
property_page::extviewer_notebook
GtkWidget * extviewer_notebook
Definition editprop.c:552
property_page::widget
GtkWidget * widget
Definition editprop.c:549
property_page::objbind_table
struct objbind_hash * objbind_table
Definition editprop.c:557
property_page::object_view
GtkWidget * object_view
Definition editprop.c:551
property_page::focused_objbind
struct objbind * focused_objbind
Definition editprop.c:560
property_page::tag_table
struct stored_tag_hash * tag_table
Definition editprop.c:558
property_page::objtype
enum editor_object_type objtype
Definition editprop.c:547
property_page::objprop_table
struct objprop_hash * objprop_table
Definition editprop.c:556
propstate
Definition editprop.c:253
propstate::property_value
struct propval * property_value
Definition editprop.c:255
propstate::property_id
int property_id
Definition editprop.c:254
propval
Definition editprop.c:242
propval::data
union propval_data data
Definition editprop.c:243
propval::valtype
enum value_types valtype
Definition editprop.c:244
propval::must_free
bool must_free
Definition editprop.c:245
research
Definition research.h:39
research::bulbs_researched
int bulbs_researched
Definition research.h:53
road_type
Definition road.h:75
startpos
Definition map.c:41
terrain
Definition terrain.h:176
tile_vision_data
Definition editprop.c:112
tile_vision_data::tile_known
bv_player tile_known
Definition editprop.c:113
tile_vision_data::tile_seen
bv_player tile_seen[V_COUNT]
Definition editprop.c:113
tile
Definition tile.h:49
tile::label
char * label
Definition tile.h:64
tile::continent
Continent_id continent
Definition tile.h:53
tileset
Definition tilespec.c:459
unit_type
Definition unittype.h:481
unit_type::hp
int hp
Definition unittype.h:505
unit
Definition unit.h:138
unit::moves_left
int moves_left
Definition unit.h:150
unit::id
int id
Definition unit.h:145
unit::moved
bool moved
Definition unit.h:173
unit::hp
int hp
Definition unit.h:151
unit::fuel
int fuel
Definition unit.h:153
unit::stay
bool stay
Definition unit.h:205
unit::done_moving
bool done_moving
Definition unit.h:181
unit::veteran
int veteran
Definition unit.h:152
view
Definition mapview_common.h:36
widget
Definition widget.h:112
world::map
struct civ_map map
Definition world_object.h:38
fc_snprintf
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:969
fc_strlcpy
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:787
fc_strcasestr
char * fc_strcasestr(const char *haystack, const char *needle)
Definition support.c:439
sz_strlcpy
#define sz_strlcpy(dest, src)
Definition support.h:161
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
sz_strlcat
#define sz_strlcat(dest, src)
Definition support.h:162
advance_name_translation
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:290
advance_index
Tech_type_id advance_index(const struct advance *padvance)
Definition tech.c:89
advance_index_iterate_end
#define advance_index_iterate_end
Definition tech.h:248
advance_iterate
#define advance_iterate(_start, _p)
Definition tech.h:264
advance_count
static Tech_type_id advance_count(void)
Definition tech.h:170
A_FIRST
#define A_FIRST
Definition tech.h:44
advance_iterate_end
#define advance_iterate_end
Definition tech.h:270
advance_index_iterate
#define advance_index_iterate(_start, _index)
Definition tech.h:244
terrain_name_translation
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:226
tile_city
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
tile.h
tile_index
#define tile_index(_pt_)
Definition tile.h:87
tile_resource
#define tile_resource(_tile)
Definition tile.h:101
tile_list_iterate
#define tile_list_iterate(tile_list, ptile)
Definition tile.h:72
tile_terrain
#define tile_terrain(_tile)
Definition tile.h:109
TILE_XY
#define TILE_XY(ptile)
Definition tile.h:42
tile_list_iterate_end
#define tile_list_iterate_end
Definition tile.h:74
tile_extras
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:119
tile_has_extra
#define tile_has_extra(ptile, pextra)
Definition tile.h:146
get_government_sprite
struct sprite * get_government_sprite(const struct tileset *t, const struct government *gov)
Definition tilespec.c:6508
tileset_full_tile_height
int tileset_full_tile_height(const struct tileset *t)
Definition tilespec.c:752
tileset_layer_in_category
bool tileset_layer_in_category(enum mapview_layer layer, enum layer_category cat)
Definition tilespec.c:7029
tileset_tile_height
int tileset_tile_height(const struct tileset *t)
Definition tilespec.c:728
tileset_full_tile_width
int tileset_full_tile_width(const struct tileset *t)
Definition tilespec.c:739
tilespec.h
mapview_layer_iterate
#define mapview_layer_iterate(layer)
Definition tilespec.h:174
mapview_layer_iterate_end
#define mapview_layer_iterate_end
Definition tilespec.h:182
layer_category
layer_category
Definition tilespec.h:188
LAYER_CATEGORY_TILE
@ LAYER_CATEGORY_TILE
Definition tilespec.h:190
LAYER_CATEGORY_CITY
@ LAYER_CATEGORY_CITY
Definition tilespec.h:189
LAYER_CATEGORY_UNIT
@ LAYER_CATEGORY_UNIT
Definition tilespec.h:191
packetdata
Definition editprop.c:95
packetdata::v_pointer2
gpointer v_pointer2
Definition editprop.c:98
packetdata::tile
struct packet_edit_tile * tile
Definition editprop.c:100
packetdata::v_pointer1
gpointer v_pointer1
Definition editprop.c:97
packetdata::unit
struct packet_edit_unit * unit
Definition editprop.c:103
packetdata::pointers
struct packetdata::@145 pointers
packetdata::player
struct packet_edit_player * player
Definition editprop.c:104
packetdata::desc
struct packet_edit_scenario_desc * desc
Definition editprop.c:107
packetdata::city
struct packet_edit_city * city
Definition editprop.c:102
packetdata::game
struct packet_edit_game * game
Definition editprop.c:106
packetdata::startpos
struct packet_edit_startpos_full * startpos
Definition editprop.c:101
propval_data
Definition editprop.c:224
propval_data::v_int
int v_int
Definition editprop.c:226
propval_data::v_gov
struct government * v_gov
Definition editprop.c:237
propval_data::v_bv_inventions
bv_techs v_bv_inventions
Definition editprop.c:238
propval_data::v_bv_special
bv_max_extras v_bv_special
Definition editprop.c:232
propval_data::v_tile_vision
struct tile_vision_data * v_tile_vision
Definition editprop.c:239
propval_data::v_string
char * v_string
Definition editprop.c:228
propval_data::v_built
struct built_status * v_built
Definition editprop.c:231
propval_data::v_bv_roads
bv_max_extras v_bv_roads
Definition editprop.c:233
propval_data::v_bool
bool v_bool
Definition editprop.c:227
propval_data::v_pointer
gpointer v_pointer
Definition editprop.c:225
propval_data::v_nation
struct nation_type * v_nation
Definition editprop.c:235
propval_data::v_nation_hash
struct nation_hash * v_nation_hash
Definition editprop.c:236
propval_data::v_bv_bases
bv_max_extras v_bv_bases
Definition editprop.c:234
propval_data::v_pixbuf
GdkPixbuf * v_pixbuf
Definition editprop.c:230
propval_data::v_const_string
const char * v_const_string
Definition editprop.c:229
unit_tile
#define unit_tile(_pu)
Definition unit.h:388
is_enemy_unit_tile
static bool is_enemy_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:411
unit_owner
#define unit_owner(_pu)
Definition unit.h:387
is_non_allied_unit_tile
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:423
unit_list_iterate
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
unit_list_iterate_end
#define unit_list_iterate_end
Definition unitlist.h:33
unit_type_get
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:123
utype_veteran_levels
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2661
utype_name_translation
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1612
utype_fuel
#define utype_fuel(ptype)
Definition unittype.h:822
vision_layer_iterate
#define vision_layer_iterate(v)
Definition vision.h:77
vision_layer_iterate_end
#define vision_layer_iterate_end
Definition vision.h:80