Freeciv-3.4
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 "nation.h"
37#include "research.h"
38#include "tile.h"
39
40/* client */
41#include "client_main.h"
42#include "climisc.h"
43#include "editor.h"
44#include "mapview_common.h"
45#include "tilespec.h"
46
47/* client/gui-gtk-4.0 */
48#include "canvas.h"
49#include "gui_main.h"
50#include "gui_stuff.h"
51#include "plrdlg.h"
52#include "sprite.h"
53
54#include "editprop.h"
55
56
57/* Forward declarations. */
58struct objprop;
59struct objbind;
60struct property_page;
61struct property_editor;
62struct extviewer;
63
64/****************************************************************************
65 Miscellaneous helpers.
66****************************************************************************/
67static GdkPixbuf *create_pixbuf_from_layers(const struct tile *ptile,
68 const struct unit *punit,
69 const struct city *pcity,
70 enum layer_category category);
71static GdkPixbuf *create_tile_pixbuf(const struct tile *ptile);
72static GdkPixbuf *create_unit_pixbuf(const struct unit *punit);
73static GdkPixbuf *create_city_pixbuf(const struct city *pcity);
74
75static void add_column(GtkWidget *view,
76 int col_id,
77 const char *name,
79 bool editable,
80 bool is_radio,
83
84static bool can_create_unit_at_tile(struct tile *ptile);
85
86static int get_next_unique_tag(void);
87
88/* 'struct stored_tag_hash' and related functions. */
89#define SPECHASH_TAG stored_tag
90#define SPECHASH_INT_KEY_TYPE
91#define SPECHASH_INT_DATA_TYPE
92#include "spechash.h"
93
94/* NB: If packet definitions change, be sure to
95 * update objbind_pack_current_values()!!! */
96union packetdata {
97 struct {
101 struct packet_edit_tile *tile;
103 struct packet_edit_city *city;
104 struct packet_edit_unit *unit;
106 struct {
107 struct packet_edit_game *game;
108 struct packet_edit_scenario_desc *desc;
110};
111
112/* Helpers for the OPID_TILE_VISION property. */
113struct tile_vision_data {
115};
116const char *vision_layer_get_name(enum vision_layer);
117
118#define PF_MAX_CLAUSES 16
119#define PF_DISJUNCTION_SEPARATOR "|"
120#define PF_CONJUNCTION_SEPARATOR "&"
121
122struct pf_pattern {
123 bool negate;
124 char *text;
125};
126
127struct pf_conjunction {
129 int count;
130};
131
132struct property_filter {
134 int count;
135};
136
137static struct property_filter *property_filter_new(const char *filter);
138static bool property_filter_match(struct property_filter *pf,
139 const struct objprop *op);
140static void property_filter_free(struct property_filter *pf);
141
142
143/****************************************************************************
144 Object type declarations.
145
146 To add a new object type:
147 1. Add a value in enum editor_object_type in client/editor.h.
148 2. Add a string name to objtype_get_name.
149 3. Add code in objtype_get_id_from_object.
150 4. Add code in objtype_get_object_from_id.
151 5. Add a case handler in objtype_is_conserved, and if
152 the object type is not conserved, then also in
153 objbind_request_destroy_object and property_page_create_objects.
154 6. Add an if-block in objbind_get_value_from_object.
155 7. Add an if-block in objbind_get_allowed_value_span.
156 9. Add a case handler in property_page_setup_objprops.
157 10. Add a case handler in property_page_add_objbinds_from_tile
158 if applicable.
159
160 Furthermore, if the object type is to be editable:
161 11. Define its edit packet in common/networking/packets.def.
162 12. Add the packet handler in server/edithand.c.
163 13. Add its edit packet type to union packetdata.
164 14. Add an if-block in objbind_pack_current_values.
165 15. Add an if-block in objbind_pack_modified_value.
166 16. Add code in property_page_new_packet.
167 17. Add code in property_page_send_packet.
168 18. Add calls to editgui_notify_object_changed in
169 client/packhand.c or where applicable.
170
171****************************************************************************/
172
173/* OBJTYPE_* enum values defined in client/editor.h */
174
175static const char *objtype_get_name(enum editor_object_type objtype);
177 gpointer object);
179 int id);
181
182
183/****************************************************************************
184 Value type declarations.
185
186 To add a new value type:
187 1. Add a value in enum value_types.
188 2. Add its field in union propval_data.
189 3. Add a case handler in valtype_get_name.
190 4. Add a case handler in propval_copy if needed.
191 5. Add a case handler in propval_free if needed.
192 6. Add a case handler in propval_equal if needed.
193 7. Add a case handler in objprop_get_gtype.
194 8. Add a case handler in property_page_set_store_value.
195 9. Add a case handler in propval_as_string if needed.
196****************************************************************************/
213
214static const char *valtype_get_name(enum value_types valtype);
215
216
217/****************************************************************************
218 Propstate and propval declarations.
219
220 To add a new member to union propval_data, see the steps for adding a
221 new value type above.
222
223 New property values are "constructed" by objbind_get_value_from_object().
224****************************************************************************/
225union propval_data {
227 int v_int;
228 bool v_bool;
229 char *v_string;
230 const char *v_const_string;
232 struct built_status *v_built;
236 struct nation_type *v_nation;
238 struct government *v_gov;
241};
242
243struct propval {
244 union propval_data data;
245 enum value_types valtype;
246 bool must_free;
247};
248
249static void propval_free(struct propval *pv);
250static void propval_free_data(struct propval *pv);
251static struct propval *propval_copy(struct propval *pv);
252static bool propval_equal(struct propval *pva, struct propval *pvb);
253
254struct propstate {
255 int property_id;
256 struct propval *property_value;
257};
258
259static struct propstate *propstate_new(struct objprop *op,
260 struct propval *pv);
261static void propstate_destroy(struct propstate *ps);
262static void propstate_clear_value(struct propstate *ps);
263static void propstate_set_value(struct propstate *ps,
264 struct propval *pv);
265static struct propval *propstate_get_value(struct propstate *ps);
266
267#define SPECHASH_TAG propstate
268#define SPECHASH_INT_KEY_TYPE
269#define SPECHASH_IDATA_TYPE struct propstate *
270#define SPECHASH_IDATA_FREE propstate_destroy
271#include "spechash.h"
272
273
274/****************************************************************************
275 Objprop declarations.
276
277 To add a new object property:
278 1. Add a value in enum object_property_ids (grouped by
279 object type).
280 2. Define the property in property_page_setup_objprops.
281 3. Add a case handler in objbind_get_value_from_object
282 in the appropriate object type block.
283 4. Add a case handler in objprop_setup_widget.
284 5. Add a case handler in objprop_refresh_widget.
285
286 Furthermore, if the property is editable:
287 5. Add a field for this property in the edit
288 packet for this object type in common/networking/packets.def.
289 6. Add a case handler in objbind_pack_modified_value.
290 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
291 !!! 7. Add code to set the packet field in !!!
292 !!! objbind_pack_current_values(). !!!
293 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
294 8. Add code to handle changes in the packet field in
295 server/edithand.c handle_edit_<objtype>.
296
297 If the property makes use of an extviewer:
298 9. Handle widget creation in extviewer_new.
299 10. Handle refresh in extviewer_refresh_widgets.
300 11. Handle clear in extviewer_clear_widgets.
301 12. Handle any signal callbacks (e.g. toggled) if needed.
302
303 TODO: Add more object properties.
304****************************************************************************/
312#ifdef FREECIV_DEBUG
314#endif /* FREECIV_DEBUG */
322 OPID_TILE_VISION, /* tile_known and tile_seen */
324
329
331#ifdef FREECIV_DEBUG
333#endif /* FREECIV_DEBUG */
344
347#ifdef FREECIV_DEBUG
349#endif /* FREECIV_DEBUG */
357
362#ifdef FREECIV_DEBUG
364#endif /* FREECIV_DEBUG */
371
383
390
391struct objprop {
392 int id;
393 const char *name;
394 const char *tooltip;
396 enum value_types valtype;
397 int column_id;
400 struct extviewer *extviewer;
402};
403
404static struct objprop *objprop_new(int id,
405 const char *name,
406 const char *tooltip,
408 enum value_types valtype,
409 struct property_page *parent);
410static int objprop_get_id(const struct objprop *op);
411static const char *objprop_get_name(const struct objprop *op);
412static const char *objprop_get_tooltip(const struct objprop *op);
413static enum value_types objprop_get_valtype(const struct objprop *op);
414static struct property_page *
416
417static bool objprop_show_in_listview(const struct objprop *op);
418static bool objprop_is_sortable(const struct objprop *op);
419static bool objprop_is_readonly(const struct objprop *op);
420static bool objprop_has_widget(const struct objprop *op);
421
422static GType objprop_get_gtype(const struct objprop *op);
423static const char *objprop_get_attribute_type_string(const struct objprop *op);
424static void objprop_set_column_id(struct objprop *op, int col_id);
425static int objprop_get_column_id(const struct objprop *op);
426static void objprop_set_treeview_column(struct objprop *op,
430
431static void objprop_setup_widget(struct objprop *op);
432static GtkWidget *objprop_get_widget(struct objprop *op);
433static void objprop_set_child_widget(struct objprop *op,
434 const char *widget_name,
437 const char *widget_name);
438static void objprop_set_extviewer(struct objprop *op,
439 struct extviewer *ev);
440static struct extviewer *objprop_get_extviewer(struct objprop *op);
441static void objprop_refresh_widget(struct objprop *op,
442 struct objbind *ob);
448
449#define SPECHASH_TAG objprop
450#define SPECHASH_INT_KEY_TYPE
451#define SPECHASH_IDATA_TYPE struct objprop *
452#include "spechash.h"
453
454
455/****************************************************************************
456 Objbind declarations.
457****************************************************************************/
458struct objbind {
460 int object_id;
464};
465
467 gpointer object);
468static void objbind_destroy(struct objbind *ob);
469static enum editor_object_type objbind_get_objtype(const struct objbind *ob);
470static void objbind_bind_properties(struct objbind *ob,
471 struct property_page *pp);
472static gpointer objbind_get_object(struct objbind *ob);
473static int objbind_get_object_id(struct objbind *ob);
474static void objbind_request_destroy_object(struct objbind *ob);
475static struct propval *objbind_get_value_from_object(struct objbind *ob,
476 struct objprop *op);
477static bool objbind_get_allowed_value_span(struct objbind *ob,
478 struct objprop *op,
479 double *pmin,
480 double *pmax,
481 double *pstep,
482 double *pbig_step);
483static bool objbind_set_modified_value(struct objbind *ob,
484 struct objprop *op,
485 struct propval *pv);
486static struct propval *objbind_get_modified_value(struct objbind *ob,
487 struct objprop *op);
488static void objbind_clear_modified_value(struct objbind *ob,
489 struct objprop *op);
490static bool objbind_property_is_modified(struct objbind *ob,
491 struct objprop *op);
492static bool objbind_has_modified_properties(struct objbind *ob);
493static void objbind_clear_all_modified_values(struct objbind *ob);
494static void objbind_pack_current_values(struct objbind *ob,
495 union packetdata packet);
496static void objbind_pack_modified_value(struct objbind *ob,
497 struct objprop *op,
498 union packetdata packet);
499static void objbind_set_rowref(struct objbind *ob,
502
503#define SPECHASH_TAG objbind
504#define SPECHASH_INT_KEY_TYPE
505#define SPECHASH_IDATA_TYPE struct objbind *
506#define SPECHASH_IDATA_FREE objbind_destroy
507#include "spechash.h"
508
509
510/****************************************************************************
511 Extended property viewer declarations. This is a set of widgets used
512 for viewing and/or editing properties with complex values (e.g. arrays).
513****************************************************************************/
514struct extviewer {
515 struct objprop *objprop;
516 struct propval *pv_cached;
517
522
525
528};
529
530static struct extviewer *extviewer_new(struct objprop *op);
531static struct objprop *extviewer_get_objprop(struct extviewer *ev);
534static void extviewer_refresh_widgets(struct extviewer *ev,
535 struct propval *pv);
536static void extviewer_clear_widgets(struct extviewer *ev);
537static void extviewer_panel_button_clicked(GtkButton *button,
540 gchar *path,
542static void extviewer_textbuf_changed(GtkTextBuffer *textbuf,
544
545
546/****************************************************************************
547 Property page declarations.
548****************************************************************************/
549struct property_page {
551
556
558
562
563 struct objbind *focused_objbind;
564};
565
566static struct property_page *
568 struct property_editor *parent);
570static const char *property_page_get_name(const struct property_page *pp);
571static enum editor_object_type
573static void property_page_load_tiles(struct property_page *pp,
574 const struct tile_list *tiles);
576 const struct tile *ptile);
577static int property_page_get_num_objbinds(const struct property_page *pp);
579static void property_page_add_objbind(struct property_page *pp,
581static void property_page_fill_widgets(struct property_page *pp);
582static struct objbind *
585 struct objbind *ob);
587 int object_id);
591 GtkTreeModel *model,
592 GtkTreePath *path,
594 gpointer data);
598 struct objprop *op,
599 struct propval *pv);
600static void property_page_send_values(struct property_page *pp);
604 struct tile_list *hint_tiles);
606static void property_page_send_packet(struct property_page *pp,
607 union packetdata packet);
608static void property_page_free_packet(struct property_page *pp,
609 union packetdata packet);
611 int object_id,
612 bool remove);
614 int tag, int object_id);
616 struct extviewer *ev);
618 struct extviewer *ev);
620 int tag, int count);
622 int tag);
623static bool property_page_tag_is_known(struct property_page *pp, int tag);
624static void property_page_clear_tags(struct property_page *pp);
633
634
635#define property_page_objprop_iterate(ARG_pp, NAME_op) \
636 TYPED_HASH_DATA_ITERATE(struct objprop *, (ARG_pp)->objprop_table, NAME_op)
637#define property_page_objprop_iterate_end HASH_DATA_ITERATE_END
638
639#define property_page_objbind_iterate(ARG_pp, NAME_ob) \
640 TYPED_HASH_DATA_ITERATE(struct objbind *, (ARG_pp)->objbind_table, NAME_ob)
641#define property_page_objbind_iterate_end HASH_DATA_ITERATE_END
642
643
644/****************************************************************************
645 Property editor declarations.
646****************************************************************************/
647struct property_editor {
650
652};
653
654static struct property_editor *property_editor_new(void);
657static struct property_page *
660
662
663
664/************************************************************************/
668{
669 switch (objtype) {
670 case OBJTYPE_TILE:
671 return _("Tile");
672 case OBJTYPE_STARTPOS:
673 return _("Start Position");
674 case OBJTYPE_UNIT:
675 return _("Unit");
676 case OBJTYPE_CITY:
677 return _("City");
678 case OBJTYPE_PLAYER:
679 return _("Player");
680 case OBJTYPE_GAME:
681 return Q_("?play:Game");
682 case NUM_OBJTYPES:
683 break;
684 }
685
686 log_error("%s() Unhandled request to get name of object type %d.",
688 return "Unknown";
689}
690
691/************************************************************************/
697 gpointer object)
698{
699 switch (objtype) {
700 case OBJTYPE_TILE:
701 return tile_index((struct tile *) object);
702 case OBJTYPE_STARTPOS:
703 return startpos_number((struct startpos *) object);
704 case OBJTYPE_UNIT:
705 return ((struct unit *) object)->id;
706 case OBJTYPE_CITY:
707 return ((struct city *) object)->id;
708 case OBJTYPE_PLAYER:
709 return player_number((struct player *) object);
710 case OBJTYPE_GAME:
711 return 1;
712 case NUM_OBJTYPES:
713 break;
714 }
715
716 log_error("%s(): Unhandled request to get object ID from object %p of "
717 "type %d (%s).", __FUNCTION__, object, objtype,
719 return -1;
720}
721
722/************************************************************************/
726 int id)
727{
728 switch (objtype) {
729 case OBJTYPE_TILE:
730 return index_to_tile(&(wld.map), id);
731 case OBJTYPE_STARTPOS:
732 return map_startpos_by_number(id);
733 case OBJTYPE_UNIT:
734 return game_unit_by_number(id);
735 case OBJTYPE_CITY:
736 return game_city_by_number(id);
737 case OBJTYPE_PLAYER:
738 return player_by_number(id);
739 case OBJTYPE_GAME:
740 return &game;
741 case NUM_OBJTYPES:
742 break;
743 }
744
745 log_error("%s(): Unhandled request to get object of type %d (%s) "
746 "with ID %d.", __FUNCTION__, objtype,
748 return NULL;
749}
750
751/************************************************************************/
757{
758 switch (objtype) {
759 case OBJTYPE_TILE:
760 case OBJTYPE_GAME:
761 return TRUE;
762 case OBJTYPE_STARTPOS:
763 case OBJTYPE_UNIT:
764 case OBJTYPE_CITY:
765 case OBJTYPE_PLAYER:
766 return FALSE;
767 case NUM_OBJTYPES:
768 break;
769 }
770
771 log_error("%s(): Unhandled request for object type %d (%s)).",
773 return TRUE;
774}
775
776/************************************************************************/
779static const char *valtype_get_name(enum value_types valtype)
780{
781 switch (valtype) {
782 case VALTYPE_NONE:
783 return "none";
784 case VALTYPE_STRING:
785 return "string";
786 case VALTYPE_INT:
787 return "int";
788 case VALTYPE_BOOL:
789 return "bool";
790 case VALTYPE_PIXBUF:
791 return "pixbuf";
793 return "struct built_status[B_LAST]";
795 return "bool[A_LAST]";
797 return "bv_special";
798 case VALTYPE_BV_ROADS:
799 return "bv_roads";
800 case VALTYPE_BV_BASES:
801 return "bv_bases";
802 case VALTYPE_NATION:
803 return "nation";
805 return "struct nation_hash";
806 case VALTYPE_GOV:
807 return "government";
809 return "struct tile_vision_data";
810 }
811
812 log_error("%s(): unhandled value type %d.", __FUNCTION__, valtype);
813 return "void";
814}
815
816/************************************************************************/
821 int col_id,
822 const char *name,
823 GType gtype,
824 bool editable,
825 bool is_radio,
828{
831 const char *attr = NULL;
832
833 if (gtype == G_TYPE_BOOLEAN) {
836 is_radio);
837 if (editable) {
839 }
840 attr = "active";
841 } else if (gtype == GDK_TYPE_PIXBUF) {
843 attr = "pixbuf";
844 } else {
846 if (editable) {
847 g_object_set(cell, "editable", TRUE, NULL);
849 }
850 attr = "text";
851 }
852
854 attr, col_id, NULL);
856}
857
858/************************************************************************/
863{
864 int count = 0;
865
867
868 switch (pv->valtype) {
869 case VALTYPE_NONE:
870 return g_strdup("");
871
872 case VALTYPE_INT:
873 return g_strdup_printf("%d", pv->data.v_int);
874
875 case VALTYPE_BOOL:
876 return g_strdup_printf("%s", pv->data.v_bool ? _("TRUE") : _("FALSE"));
877
878 case VALTYPE_NATION:
879 return g_strdup_printf("%s", nation_adjective_translation(pv->data.v_nation));
880
881 case VALTYPE_GOV:
882 if (pv->data.v_gov != NULL) {
883 return g_strdup_printf("%s", government_name_translation(pv->data.v_gov));
884 } else {
886 }
887
889 {
890 int great_wonder_count = 0, small_wonder_count = 0, building_count = 0;
891 int id;
892
893 improvement_iterate(pimprove) {
894 id = improvement_index(pimprove);
895 if (pv->data.v_built[id].turn < 0) {
896 continue;
897 }
898 if (is_great_wonder(pimprove)) {
900 } else if (is_small_wonder(pimprove)) {
902 } else {
903 building_count++;
904 }
906 /* TRANS: "Number of buildings, number of small
907 * wonders (e.g. palace), number of great wonders." */
908 return g_strdup_printf(_("%db %ds %dW"),
909 building_count, small_wonder_count,
911 }
912
915 if (BV_ISSET(pv->data.v_bv_inventions, tech)) {
916 count++;
917 }
919 /* TRANS: "Number of technologies known". */
920 return g_strdup_printf(_("%d known"), count);
921
924 if (BV_ISSET(pv->data.v_bv_special, spe->data.special_idx)) {
925 count++;
926 }
928 /* TRANS: "The number of terrain specials (e.g. hut,
929 * river, pollution, etc.) present on a tile." */
930 return g_strdup_printf(_("%d present"), count);
931
932 case VALTYPE_BV_ROADS:
934 struct road_type *proad = extra_road_get(pextra);
935
936 if (BV_ISSET(pv->data.v_bv_roads, road_number(proad))) {
937 count++;
938 }
940 return g_strdup_printf(_("%d present"), count);
941
942 case VALTYPE_BV_BASES:
944 struct base_type *pbase = extra_base_get(pextra);
945
946 if (BV_ISSET(pv->data.v_bv_bases, base_number(pbase))) {
947 count++;
948 }
950 return g_strdup_printf(_("%d present"), count);
951
953 count = nation_hash_size(pv->data.v_nation_hash);
954 if (0 == count) {
955 return g_strdup(_("All nations"));
956 } else {
957 return g_strdup_printf(PL_("%d nation", "%d nations",
958 count), count);
959 }
960
961 case VALTYPE_STRING:
962 /* Assume it is a very long string. */
963 count = strlen(pv->data.v_const_string);
964 return g_strdup_printf(PL_("%d byte", "%d bytes", count),
965 count);
966
967 case VALTYPE_PIXBUF:
969 break;
970 }
971
972 log_error("%s(): Unhandled value type %d for property value %p.",
973 __FUNCTION__, pv->valtype, pv);
974 return g_strdup("");
975}
976
977/************************************************************************/
982{
983 int turn_built;
984
985 turn_built = bs->turn;
986
987 if (turn_built == I_NEVER) {
988 /* TRANS: Improvement never built. */
989 return g_strdup(_("(never)"));
990 } else if (turn_built == I_DESTROYED) {
991 /* TRANS: Improvement was destroyed. */
992 return g_strdup(_("(destroyed)"));
993 } else {
994 return g_strdup_printf("%d", turn_built);
995 }
996}
997
998/************************************************************************/
1002static bool can_create_unit_at_tile(struct tile *ptile)
1003{
1004 struct unit *vunit;
1005 struct city *pcity;
1006 struct player *pplayer;
1007 bool ret;
1008
1009 if (!ptile) {
1010 return FALSE;
1011 }
1012
1014 if (!vunit) {
1015 return FALSE;
1016 }
1017
1018 pcity = tile_city(ptile);
1019 pplayer = unit_owner(vunit);
1020
1021 ret = (can_unit_exist_at_tile(&(wld.map), vunit, ptile)
1022 && !is_non_allied_unit_tile(ptile, pplayer,
1024 && (pcity == NULL
1026 unit_owner(vunit))));
1027 free(vunit);
1028
1029 return ret;
1030}
1031
1032/************************************************************************/
1035static int get_next_unique_tag(void)
1036{
1037 static int tag_series = 0;
1038
1039 tag_series++;
1040 return tag_series;
1041}
1042
1043/************************************************************************/
1046static struct propval *propval_copy(struct propval *pv)
1047{
1048 struct propval *pv_copy;
1049 size_t size;
1050
1051 if (!pv) {
1052 return NULL;
1053 }
1054
1055 pv_copy = fc_calloc(1, sizeof(*pv));
1056 pv_copy->valtype = pv->valtype;
1057
1058 switch (pv->valtype) {
1059 case VALTYPE_NONE:
1060 return pv_copy;
1061 case VALTYPE_INT:
1062 pv_copy->data.v_int = pv->data.v_int;
1063 return pv_copy;
1064 case VALTYPE_BOOL:
1065 pv_copy->data.v_bool = pv->data.v_bool;
1066 return pv_copy;
1067 case VALTYPE_STRING:
1068 pv_copy->data.v_string = fc_strdup(pv->data.v_string);
1069 pv_copy->must_free = TRUE;
1070 return pv_copy;
1071 case VALTYPE_PIXBUF:
1072 g_object_ref(pv->data.v_pixbuf);
1073 pv_copy->data.v_pixbuf = pv->data.v_pixbuf;
1074 pv_copy->must_free = TRUE;
1075 return pv_copy;
1077 size = B_LAST * sizeof(struct built_status);
1078 pv_copy->data.v_pointer = fc_malloc(size);
1079 memcpy(pv_copy->data.v_pointer, pv->data.v_pointer, size);
1080 pv_copy->must_free = TRUE;
1081 return pv_copy;
1082 case VALTYPE_BV_SPECIAL:
1083 pv_copy->data.v_bv_special = pv->data.v_bv_special;
1084 return pv_copy;
1085 case VALTYPE_BV_ROADS:
1086 pv_copy->data.v_bv_roads = pv->data.v_bv_roads;
1087 return pv_copy;
1088 case VALTYPE_BV_BASES:
1089 pv_copy->data.v_bv_bases = pv->data.v_bv_bases;
1090 return pv_copy;
1091 case VALTYPE_NATION:
1092 pv_copy->data.v_nation = pv->data.v_nation;
1093 return pv_copy;
1094 case VALTYPE_GOV:
1095 pv_copy->data.v_gov = pv->data.v_gov;
1096 return pv_copy;
1098 pv_copy->data.v_nation_hash
1099 = nation_hash_copy(pv->data.v_nation_hash);
1100 pv_copy->must_free = TRUE;
1101 return pv_copy;
1103 pv_copy->data.v_bv_inventions = pv->data.v_bv_inventions;
1104 return pv_copy;
1106 size = sizeof(struct tile_vision_data);
1107 pv_copy->data.v_tile_vision = fc_malloc(size);
1108 pv_copy->data.v_tile_vision->tile_known
1109 = pv->data.v_tile_vision->tile_known;
1111 pv_copy->data.v_tile_vision->tile_seen[v]
1112 = pv->data.v_tile_vision->tile_seen[v];
1114 pv_copy->must_free = TRUE;
1115 return pv_copy;
1116 }
1117
1118 log_error("%s(): Unhandled value type %d for property value %p.",
1119 __FUNCTION__, pv->valtype, pv);
1120 pv_copy->data = pv->data;
1121 return pv_copy;
1122}
1123
1124/************************************************************************/
1128static void propval_free(struct propval *pv)
1129{
1130 if (!pv) {
1131 return;
1132 }
1133
1135 free(pv);
1136}
1137
1138/************************************************************************/
1142static void propval_free_data(struct propval *pv)
1143{
1144 if (!pv || !pv->must_free) {
1145 return;
1146 }
1147
1148 switch (pv->valtype) {
1149 case VALTYPE_NONE:
1150 case VALTYPE_INT:
1151 case VALTYPE_BOOL:
1152 case VALTYPE_BV_SPECIAL:
1153 case VALTYPE_BV_ROADS:
1154 case VALTYPE_BV_BASES:
1155 case VALTYPE_NATION:
1156 case VALTYPE_GOV:
1157 return;
1158 case VALTYPE_PIXBUF:
1159 g_object_unref(pv->data.v_pixbuf);
1160 return;
1161 case VALTYPE_STRING:
1165 free(pv->data.v_pointer);
1166 return;
1168 nation_hash_destroy(pv->data.v_nation_hash);
1169 return;
1170 }
1171
1172 log_error("%s(): Unhandled request to free data %p (type %s).",
1173 __FUNCTION__, pv->data.v_pointer, valtype_get_name(pv->valtype));
1174}
1175
1176/************************************************************************/
1179static bool propval_equal(struct propval *pva,
1180 struct propval *pvb)
1181{
1182 if (!pva || !pvb) {
1183 return pva == pvb;
1184 }
1185
1186 if (pva->valtype != pvb->valtype) {
1187 return FALSE;
1188 }
1189
1190 switch (pva->valtype) {
1191 case VALTYPE_NONE:
1192 return TRUE;
1193 case VALTYPE_INT:
1194 return pva->data.v_int == pvb->data.v_int;
1195 case VALTYPE_BOOL:
1196 return pva->data.v_bool == pvb->data.v_bool;
1197 case VALTYPE_STRING:
1198 if (pva->data.v_const_string != NULL
1199 && pvb->data.v_const_string != NULL) {
1200 return !strcmp(pva->data.v_const_string,
1201 pvb->data.v_const_string);
1202 }
1203 return pva->data.v_const_string == pvb->data.v_const_string;
1204 case VALTYPE_PIXBUF:
1205 return pva->data.v_pixbuf == pvb->data.v_pixbuf;
1207 if (pva->data.v_pointer == pvb->data.v_pointer) {
1208 return TRUE;
1209 } else if (!pva->data.v_pointer || !pvb->data.v_pointer) {
1210 return FALSE;
1211 }
1212
1213 improvement_iterate(pimprove) {
1214 int id, vatb, vbtb;
1215
1216 id = improvement_index(pimprove);
1217 vatb = pva->data.v_built[id].turn;
1218 vbtb = pvb->data.v_built[id].turn;
1219 if (vatb < 0 && vbtb < 0) {
1220 continue;
1221 }
1222 if (vatb != vbtb) {
1223 return FALSE;
1224 }
1226 return TRUE;
1228 return BV_ARE_EQUAL(pva->data.v_bv_inventions, pvb->data.v_bv_inventions);
1229 case VALTYPE_BV_SPECIAL:
1230 return BV_ARE_EQUAL(pva->data.v_bv_special, pvb->data.v_bv_special);
1231 case VALTYPE_BV_ROADS:
1232 return BV_ARE_EQUAL(pva->data.v_bv_roads, pvb->data.v_bv_roads);
1233 case VALTYPE_BV_BASES:
1234 return BV_ARE_EQUAL(pva->data.v_bv_bases, pvb->data.v_bv_bases);
1235 case VALTYPE_NATION:
1236 return pva->data.v_nation == pvb->data.v_nation;
1238 return nation_hashes_are_equal(pva->data.v_nation_hash,
1239 pvb->data.v_nation_hash);
1240 case VALTYPE_GOV:
1241 return pva->data.v_gov == pvb->data.v_gov;
1243 if (!BV_ARE_EQUAL(pva->data.v_tile_vision->tile_known,
1244 pvb->data.v_tile_vision->tile_known)) {
1245 return FALSE;
1246 }
1248 if (!BV_ARE_EQUAL(pva->data.v_tile_vision->tile_seen[v],
1249 pvb->data.v_tile_vision->tile_seen[v])) {
1250 return FALSE;
1251 }
1253 return TRUE;
1254 }
1255
1256 log_error("%s(): Unhandled value type %d for property values %p and %p.",
1257 __FUNCTION__, pva->valtype, pva, pvb);
1258 return pva->data.v_pointer == pvb->data.v_pointer;
1259}
1260
1261/************************************************************************/
1267static struct propstate *propstate_new(struct objprop *op,
1268 struct propval *pv)
1269{
1270 struct propstate *ps;
1271
1272 if (!op) {
1273 return NULL;
1274 }
1275
1276 ps = fc_calloc(1, sizeof(*ps));
1277 ps->property_id = objprop_get_id(op);
1278 ps->property_value = pv;
1279
1280 return ps;
1281}
1282
1283/************************************************************************/
1287{
1288 if (!ps) {
1289 return;
1290 }
1291
1292 propval_free(ps->property_value);
1293 ps->property_value = NULL;
1294}
1295
1296/************************************************************************/
1299static void propstate_destroy(struct propstate *ps)
1300{
1301 if (!ps) {
1302 return;
1303 }
1305 free(ps);
1306}
1307
1308/************************************************************************/
1315 struct propval *pv)
1316{
1317 if (!ps) {
1318 return;
1319 }
1321 ps->property_value = pv;
1322}
1323
1324/************************************************************************/
1330{
1331 if (!ps) {
1332 return NULL;
1333 }
1334 return ps->property_value;
1335}
1336
1337/************************************************************************/
1342 gpointer object)
1343{
1344 struct objbind *ob;
1345 int id;
1346
1347 if (object == NULL) {
1348 return NULL;
1349 }
1350
1351 id = objtype_get_id_from_object(objtype, object);
1352 if (id < 0) {
1353 return NULL;
1354 }
1355
1356 ob = fc_calloc(1, sizeof(*ob));
1357 ob->object_id = id;
1358 ob->objtype = objtype;
1359 ob->propstate_table = propstate_hash_new();
1360
1361 return ob;
1362}
1363
1364/************************************************************************/
1368{
1369 int id;
1370
1371 if (!ob) {
1372 return NULL;
1373 }
1374
1376
1377 return objtype_get_object_from_id(ob->objtype, id);
1378}
1379
1380/************************************************************************/
1384{
1385 if (NULL == ob) {
1386 return -1;
1387 }
1388 return ob->object_id;
1389}
1390
1391/************************************************************************/
1397{
1398 struct connection *my_conn = &client.conn;
1400 int id;
1401
1402 if (!ob) {
1403 return;
1404 }
1405
1408 return;
1409 }
1410
1412
1413 switch (objtype) {
1414 case OBJTYPE_STARTPOS:
1416 return;
1417 case OBJTYPE_UNIT:
1419 return;
1420 case OBJTYPE_CITY:
1422 return;
1423 case OBJTYPE_PLAYER:
1425 return;
1426 case OBJTYPE_TILE:
1427 case OBJTYPE_GAME:
1428 case NUM_OBJTYPES:
1429 break;
1430 }
1431
1432 log_error("%s(): Unhandled request to destroy object %p (ID %d) of type "
1433 "%d (%s).", __FUNCTION__, objbind_get_object(ob), id, objtype,
1435}
1436
1437/************************************************************************/
1445 struct objprop *op)
1446{
1449 struct propval *pv;
1450
1451 if (!ob || !op) {
1452 return NULL;
1453 }
1454
1457
1458 pv = fc_calloc(1, sizeof(*pv));
1459 pv->valtype = objprop_get_valtype(op);
1460
1461 switch (objtype) {
1462 case OBJTYPE_TILE:
1463 {
1464 const struct tile *ptile = objbind_get_object(ob);
1465 int tile_x, tile_y, nat_x, nat_y;
1466
1467 if (NULL == ptile) {
1468 goto FAILED;
1469 }
1470
1473
1474 switch (propid) {
1475 case OPID_TILE_IMAGE:
1476 pv->data.v_pixbuf = create_tile_pixbuf(ptile);
1477 pv->must_free = TRUE;
1478 break;
1479#ifdef FREECIV_DEBUG
1480 case OPID_TILE_ADDRESS:
1481 pv->data.v_string = g_strdup_printf("%p", ptile);
1482 pv->must_free = TRUE;
1483 break;
1484#endif /* FREECIV_DEBUG */
1485 case OPID_TILE_TERRAIN:
1486 {
1487 const struct terrain *pterrain = tile_terrain(ptile);
1488
1489 if (NULL != pterrain) {
1490 pv->data.v_const_string = terrain_name_translation(pterrain);
1491 } else {
1492 pv->data.v_const_string = "";
1493 }
1494 }
1495 break;
1496 case OPID_TILE_RESOURCE:
1497 {
1498 const struct extra_type *presource = tile_resource(ptile);
1499
1500 if (NULL != presource) {
1501 pv->data.v_const_string = extra_name_translation(presource);
1502 } else {
1503 pv->data.v_const_string = "";
1504 }
1505 }
1506 break;
1507 case OPID_TILE_XY:
1508 pv->data.v_string = g_strdup_printf("(%d, %d)", tile_x, tile_y);
1509 pv->must_free = TRUE;
1510 break;
1511 case OPID_TILE_INDEX:
1512 pv->data.v_int = tile_index(ptile);
1513 break;
1514 case OPID_TILE_X:
1515 pv->data.v_int = tile_x;
1516 break;
1517 case OPID_TILE_Y:
1518 pv->data.v_int = tile_y;
1519 break;
1520 case OPID_TILE_NAT_X:
1521 pv->data.v_int = nat_x;
1522 break;
1523 case OPID_TILE_NAT_Y:
1524 pv->data.v_int = nat_y;
1525 break;
1527 pv->data.v_int = ptile->continent;
1528 break;
1529 case OPID_TILE_SPECIALS:
1530 BV_CLR_ALL(pv->data.v_bv_special);
1532 if (tile_has_extra(ptile, pextra)) {
1533 BV_SET(pv->data.v_bv_special, pextra->data.special_idx);
1534 }
1536 break;
1537 case OPID_TILE_ROADS:
1538 BV_CLR_ALL(pv->data.v_bv_roads);
1540 if (tile_has_extra(ptile, pextra)) {
1541 BV_SET(pv->data.v_bv_roads, road_number(extra_road_get(pextra)));
1542 }
1544 break;
1545 case OPID_TILE_BASES:
1546 BV_CLR_ALL(pv->data.v_bv_bases);
1548 if (tile_has_extra(ptile, pextra)) {
1549 BV_SET(pv->data.v_bv_bases, base_number(extra_base_get(pextra)));
1550 }
1552 break;
1553 case OPID_TILE_VISION:
1554 pv->data.v_tile_vision = fc_malloc(sizeof(struct tile_vision_data));
1555
1556 /* The server saves the known tiles and the player vision in special
1557 * bitvectors with the number of tiles as index. Here we want the
1558 * information for one tile. Thus, the data is transformed to
1559 * bitvectors with the number of player slots as index. */
1560 BV_CLR_ALL(pv->data.v_tile_vision->tile_known);
1561 players_iterate(pplayer) {
1562 if (dbv_isset(&pplayer->tile_known, tile_index(ptile))) {
1563 BV_SET(pv->data.v_tile_vision->tile_known,
1564 player_index(pplayer));
1565 }
1567
1569 BV_CLR_ALL(pv->data.v_tile_vision->tile_seen[v]);
1570 players_iterate(pplayer) {
1571 if (fc_funcs->player_tile_vision_get(ptile, pplayer, v)) {
1572 BV_SET(pv->data.v_tile_vision->tile_seen[v],
1573 player_index(pplayer));
1574 }
1577 pv->must_free = TRUE;
1578 break;
1579 case OPID_TILE_LABEL:
1580 if (ptile->label != NULL) {
1581 pv->data.v_const_string = ptile->label;
1582 } else {
1583 pv->data.v_const_string = "";
1584 }
1585 break;
1586 default:
1587 log_error("%s(): Unhandled request for value of property %d "
1588 "(%s) from object of type \"%s\".", __FUNCTION__,
1590 goto FAILED;
1591 }
1592 }
1593 return pv;
1594
1595 case OBJTYPE_STARTPOS:
1596 {
1597 const struct startpos *psp = objbind_get_object(ob);
1598 const struct tile *ptile;
1599
1600 if (NULL == psp) {
1601 goto FAILED;
1602 }
1603
1604 switch (propid) {
1606 ptile = startpos_tile(psp);
1607 pv->data.v_pixbuf = create_tile_pixbuf(ptile);
1608 pv->must_free = TRUE;
1609 break;
1610 case OPID_STARTPOS_XY:
1611 ptile = startpos_tile(psp);
1612 pv->data.v_string = g_strdup_printf("(%d, %d)", TILE_XY(ptile));
1613 pv->must_free = TRUE;
1614 break;
1616 pv->data.v_bool = startpos_is_excluding(psp);
1617 break;
1619 pv->data.v_nation_hash = nation_hash_copy(startpos_raw_nations(psp));
1620 pv->must_free = TRUE;
1621 break;
1622 default:
1623 log_error("%s(): Unhandled request for value of property %d "
1624 "(%s) from object of type \"%s\".", __FUNCTION__,
1626 goto FAILED;
1627 }
1628 }
1629 return pv;
1630
1631 case OBJTYPE_UNIT:
1632 {
1633 struct unit *punit = objbind_get_object(ob);
1634
1635 if (NULL == punit) {
1636 goto FAILED;
1637 }
1638
1639 switch (propid) {
1640 case OPID_UNIT_IMAGE:
1641 pv->data.v_pixbuf = create_unit_pixbuf(punit);
1642 pv->must_free = TRUE;
1643 break;
1644#ifdef FREECIV_DEBUG
1645 case OPID_UNIT_ADDRESS:
1646 pv->data.v_string = g_strdup_printf("%p", punit);
1647 pv->must_free = TRUE;
1648 break;
1649#endif /* FREECIV_DEBUG */
1650 case OPID_UNIT_XY:
1651 {
1652 const struct tile *ptile = unit_tile(punit);
1653
1654 pv->data.v_string = g_strdup_printf("(%d, %d)", TILE_XY(ptile));
1655 pv->must_free = TRUE;
1656 }
1657 break;
1658 case OPID_UNIT_ID:
1659 pv->data.v_int = punit->id;
1660 break;
1661 case OPID_UNIT_TYPE:
1662 {
1663 const struct unit_type *putype = unit_type_get(punit);
1664
1665 pv->data.v_const_string = utype_name_translation(putype);
1666 }
1667 break;
1669 pv->data.v_int = punit->moves_left;
1670 break;
1671 case OPID_UNIT_FUEL:
1672 pv->data.v_int = punit->fuel;
1673 break;
1674 case OPID_UNIT_MOVED:
1675 pv->data.v_bool = punit->moved;
1676 break;
1678 pv->data.v_bool = punit->done_moving;
1679 break;
1680 case OPID_UNIT_HP:
1681 pv->data.v_int = punit->hp;
1682 break;
1683 case OPID_UNIT_VETERAN:
1684 pv->data.v_int = punit->veteran;
1685 break;
1686 case OPID_UNIT_STAY:
1687 pv->data.v_bool = punit->stay;
1688 break;
1689 default:
1690 log_error("%s(): Unhandled request for value of property %d "
1691 "(%s) from object of type \"%s\".", __FUNCTION__,
1693 goto FAILED;
1694 }
1695 }
1696 return pv;
1697
1698 case OBJTYPE_CITY:
1699 {
1700 const struct city *pcity = objbind_get_object(ob);
1701
1702 if (NULL == pcity) {
1703 goto FAILED;
1704 }
1705
1706 switch (propid) {
1707 case OPID_CITY_IMAGE:
1708 pv->data.v_pixbuf = create_city_pixbuf(pcity);
1709 pv->must_free = TRUE;
1710 break;
1711#ifdef FREECIV_DEBUG
1712 case OPID_CITY_ADDRESS:
1713 pv->data.v_string = g_strdup_printf("%p", pcity);
1714 pv->must_free = TRUE;
1715 break;
1716#endif /* FREECIV_DEBUG */
1717 case OPID_CITY_XY:
1718 {
1719 const struct tile *ptile = city_tile(pcity);
1720
1721 pv->data.v_string = g_strdup_printf("(%d, %d)", TILE_XY(ptile));
1722 pv->must_free = TRUE;
1723 }
1724 break;
1725 case OPID_CITY_ID:
1726 pv->data.v_int = pcity->id;
1727 break;
1728 case OPID_CITY_NAME:
1729 pv->data.v_const_string = pcity->name;
1730 break;
1731 case OPID_CITY_SIZE:
1732 pv->data.v_int = city_size_get(pcity);
1733 break;
1734 case OPID_CITY_HISTORY:
1735 pv->data.v_int = pcity->history;
1736 break;
1738 pv->data.v_built = fc_malloc(sizeof(pcity->built));
1739 memcpy(pv->data.v_built, pcity->built, sizeof(pcity->built));
1740 pv->must_free = TRUE;
1741 break;
1743 pv->data.v_int = pcity->food_stock;
1744 break;
1746 pv->data.v_int = pcity->shield_stock;
1747 break;
1748 default:
1749 log_error("%s(): Unhandled request for value of property %d "
1750 "(%s) from object of type \"%s\".", __FUNCTION__,
1752 goto FAILED;
1753 }
1754 }
1755 return pv;
1756
1757 case OBJTYPE_PLAYER:
1758 {
1759 const struct player *pplayer = objbind_get_object(ob);
1760 const struct research *presearch;
1761
1762 if (NULL == pplayer) {
1763 goto FAILED;
1764 }
1765
1766 switch (propid) {
1767 case OPID_PLAYER_NAME:
1768 pv->data.v_const_string = pplayer->name;
1769 break;
1770 case OPID_PLAYER_NATION:
1771 pv->data.v_nation = nation_of_player(pplayer);
1772 break;
1773 case OPID_PLAYER_GOV:
1774 pv->data.v_gov = pplayer->government;
1775 break;
1776 case OPID_PLAYER_AGE:
1777 pv->data.v_int = pplayer->turns_alive;
1778 break;
1779#ifdef FREECIV_DEBUG
1781 pv->data.v_string = g_strdup_printf("%p", pplayer);
1782 pv->must_free = TRUE;
1783 break;
1784#endif /* FREECIV_DEBUG */
1786 presearch = research_get(pplayer);
1787 BV_CLR_ALL(pv->data.v_bv_inventions);
1790 BV_SET(pv->data.v_bv_inventions, tech);
1791 }
1793 break;
1795 pv->data.v_bool = player_has_flag(pplayer, PLRF_SCENARIO_RESERVED);
1796 break;
1798 pv->data.v_int = pplayer->autoselect_weight;
1799 break;
1801 presearch = research_get(pplayer);
1802 pv->data.v_int = presearch->bulbs_researched;
1803 break;
1804 case OPID_PLAYER_GOLD:
1805 pv->data.v_int = pplayer->economic.gold;
1806 break;
1808 pv->data.v_int = pplayer->economic.infra_points;
1809 break;
1810 default:
1811 log_error("%s(): Unhandled request for value of property %d "
1812 "(%s) from object of type \"%s\".", __FUNCTION__,
1814 goto FAILED;
1815 }
1816 }
1817 return pv;
1818
1819 case OBJTYPE_GAME:
1820 {
1821 const struct civ_game *pgame = objbind_get_object(ob);
1822
1823 if (NULL == pgame) {
1824 goto FAILED;
1825 }
1826
1827 switch (propid) {
1828 case OPID_GAME_SCENARIO:
1829 pv->data.v_bool = pgame->scenario.is_scenario;
1830 break;
1832 pv->data.v_const_string = pgame->scenario.name;
1833 break;
1835 pv->data.v_const_string = pgame->scenario.authors;
1836 break;
1838 pv->data.v_const_string = pgame->scenario_desc.description;
1839 break;
1841 pv->data.v_bool = pgame->scenario.save_random;
1842 break;
1844 pv->data.v_bool = pgame->scenario.players;
1845 break;
1847 pv->data.v_bool = pgame->scenario.startpos_nations;
1848 break;
1850 pv->data.v_bool = pgame->scenario.prevent_new_cities;
1851 break;
1853 pv->data.v_bool = pgame->scenario.lake_flooding;
1854 break;
1856 pv->data.v_bool = pgame->scenario.ruleset_locked;
1857 break;
1858 default:
1859 log_error("%s(): Unhandled request for value of property %d "
1860 "(%s) from object of type \"%s\".", __FUNCTION__,
1862 goto FAILED;
1863 }
1864 }
1865 return pv;
1866
1867 case NUM_OBJTYPES:
1868 break;
1869 }
1870
1871 log_error("%s(): Unhandled request for object type \"%s\" (nb %d).",
1873
1874FAILED:
1875 if (NULL != pv) {
1876 free(pv);
1877 }
1878 return NULL;
1879}
1880
1881/************************************************************************/
1886 struct objprop *op,
1887 double *pmin,
1888 double *pmax,
1889 double *pstep,
1890 double *pbig_step)
1891{
1894 double dummy;
1895
1896 /* Fill the values with something. */
1897 if (NULL != pmin) {
1898 *pmin = 0;
1899 } else {
1900 pmin = &dummy;
1901 }
1902 if (NULL != pmax) {
1903 *pmax = 1;
1904 } else {
1905 pmax = &dummy;
1906 }
1907 if (NULL != pstep) {
1908 *pstep = 1;
1909 } else {
1910 pstep = &dummy;
1911 }
1912 if (NULL != pbig_step) {
1913 *pbig_step = 1;
1914 } else {
1915 pbig_step = &dummy;
1916 }
1917
1918 if (!ob || !op) {
1919 return FALSE;
1920 }
1921
1924
1925 switch (objtype) {
1926 case OBJTYPE_TILE:
1927 case OBJTYPE_STARTPOS:
1928 log_error("%s(): Unhandled request for value range of property %d (%s) "
1929 "from object of type \"%s\".", __FUNCTION__,
1931 return FALSE;
1932
1933 case OBJTYPE_UNIT:
1934 {
1935 const struct unit *punit = objbind_get_object(ob);
1936 const struct unit_type *putype;
1937
1938 if (NULL == punit) {
1939 return FALSE;
1940 }
1941
1943
1944 switch (propid) {
1946 *pmin = 0;
1948 *pstep = 1;
1949 *pbig_step = 5;
1950 return TRUE;
1951 case OPID_UNIT_FUEL:
1952 *pmin = 0;
1954 *pstep = 1;
1955 *pbig_step = 5;
1956 return TRUE;
1957 case OPID_UNIT_HP:
1958 *pmin = 1;
1959 *pmax = putype->hp;
1960 *pstep = 1;
1961 *pbig_step = 10;
1962 return TRUE;
1963 case OPID_UNIT_VETERAN:
1964 *pmin = 0;
1966 *pstep = 1;
1967 *pbig_step = 3;
1968 return TRUE;
1969 default:
1970 break;
1971 }
1972 }
1973 log_error("%s(): Unhandled request for value range of property %d (%s) "
1974 "from object of type \"%s\".", __FUNCTION__,
1976 return FALSE;
1977
1978 case OBJTYPE_CITY:
1979 {
1980 const struct city *pcity = objbind_get_object(ob);
1981
1982 if (NULL == pcity) {
1983 return FALSE;
1984 }
1985
1986 switch (propid) {
1987 case OPID_CITY_SIZE:
1988 *pmin = 1;
1990 *pstep = 1;
1991 *pbig_step = 5;
1992 return TRUE;
1993 case OPID_CITY_HISTORY:
1994 *pmin = 0;
1995 *pmax = USHRT_MAX;
1996 *pstep = 1;
1997 *pbig_step = 10;
1998 return TRUE;
2000 *pmin = 0;
2002 *pstep = 1;
2003 *pbig_step = 5;
2004 return TRUE;
2006 *pmin = 0;
2007 *pmax = USHRT_MAX; /* Limited to uint16 by city info packet. */
2008 *pstep = 1;
2009 *pbig_step = 10;
2010 return TRUE;
2011 default:
2012 break;
2013 }
2014 }
2015 log_error("%s(): Unhandled request for value range of property %d (%s) "
2016 "from object of type \"%s\".", __FUNCTION__,
2018 return FALSE;
2019
2020 case OBJTYPE_PLAYER:
2021 switch (propid) {
2023 *pmin = 0;
2024 *pmax = 1000000; /* Arbitrary. */
2025 *pstep = 1;
2026 *pbig_step = 100;
2027 return TRUE;
2028 case OPID_PLAYER_GOLD:
2029 *pmin = 0;
2030 *pmax = 1000000; /* Arbitrary. */
2031 *pstep = 1;
2032 *pbig_step = 100;
2033 return TRUE;
2035 *pmin = 0;
2036 *pmax = 1000000; /* Arbitrary. */
2037 *pstep = 1;
2038 *pbig_step = 100;
2039 return TRUE;
2041 *pmin = -1;
2042 *pmax = 10000; /* Keep it under SINT16 */
2043 *pstep = 1;
2044 *pbig_step = 10;
2045 return TRUE;
2046 default:
2047 break;
2048 }
2049 log_error("%s(): Unhandled request for value range of property %d (%s) "
2050 "from object of type \"%s\".", __FUNCTION__,
2052 return FALSE;
2053
2054 case OBJTYPE_GAME:
2055 log_error("%s(): Unhandled request for value range of property %d (%s) "
2056 "from object of type \"%s\".", __FUNCTION__,
2058 return FALSE;
2059
2060 case NUM_OBJTYPES:
2061 break;
2062 }
2063
2064 log_error("%s(): Unhandled request for object type \"%s\" (nb %d).",
2066 return FALSE;
2067}
2068
2069/************************************************************************/
2073 struct objprop *op)
2074{
2075 if (!ob || !op || !ob->propstate_table) {
2076 return;
2077 }
2078
2079 propstate_hash_remove(ob->propstate_table, objprop_get_id(op));
2080}
2081
2082/************************************************************************/
2087 struct objprop *op)
2088{
2089 if (!ob || !op) {
2090 return FALSE;
2091 }
2092
2093 if (objprop_is_readonly(op)) {
2094 return FALSE;
2095 }
2096
2097 return propstate_hash_lookup(ob->propstate_table,
2099}
2100
2101/************************************************************************/
2106{
2107 if (!ob) {
2108 return FALSE;
2109 }
2110
2111 return (0 < propstate_hash_size(ob->propstate_table));
2112}
2113
2114/************************************************************************/
2118{
2119 if (!ob) {
2120 return;
2121 }
2122 propstate_hash_clear(ob->propstate_table);
2123}
2124
2125/************************************************************************/
2132 struct objprop *op,
2133 struct propval *pv)
2134{
2135 struct propstate *ps;
2136 bool equal;
2137 struct propval *pv_old, *pv_copy;
2139
2140 if (!ob || !op) {
2141 return FALSE;
2142 }
2143
2145
2147 if (!pv_old) {
2148 return FALSE;
2149 }
2150
2153
2154 if (equal) {
2156 return FALSE;
2157 }
2158
2160
2161 if (propstate_hash_lookup(ob->propstate_table, propid, &ps)) {
2163 } else {
2165 propstate_hash_insert(ob->propstate_table, propid, ps);
2166 }
2167
2168 return TRUE;
2169}
2170
2171/************************************************************************/
2178 struct objprop *op)
2179{
2180 struct propstate *ps;
2181
2182 if (!ob || !op) {
2183 return NULL;
2184 }
2185
2186 if (propstate_hash_lookup(ob->propstate_table, objprop_get_id(op), &ps)) {
2187 return propstate_get_value(ps);
2188 } else {
2189 return NULL;
2190 }
2191}
2192
2193/************************************************************************/
2196static void objbind_destroy(struct objbind *ob)
2197{
2198 if (!ob) {
2199 return;
2200 }
2201 if (ob->propstate_table) {
2202 propstate_hash_destroy(ob->propstate_table);
2203 ob->propstate_table = NULL;
2204 }
2205 if (ob->rowref) {
2207 ob->rowref = NULL;
2208 }
2209 free(ob);
2210}
2211
2212/************************************************************************/
2216{
2217 if (!ob) {
2218 return NUM_OBJTYPES;
2219 }
2220 return ob->objtype;
2221}
2222
2223/************************************************************************/
2227 struct property_page *pp)
2228{
2229 if (!ob) {
2230 return;
2231 }
2232 ob->parent_property_page = pp;
2233}
2234
2235/************************************************************************/
2241 union packetdata pd)
2242{
2244
2245 if (!ob || !pd.pointers.v_pointer1) {
2246 return;
2247 }
2248
2250
2251 switch (objtype) {
2252 case OBJTYPE_TILE:
2253 {
2254 struct packet_edit_tile *packet = pd.tile;
2255 const struct tile *ptile = objbind_get_object(ob);
2256
2257 if (NULL == ptile) {
2258 return;
2259 }
2260
2261 packet->tile = tile_index(ptile);
2262 packet->extras = *tile_extras(ptile);
2263 /* TODO: Set more packet fields. */
2264 }
2265 return;
2266
2267 case OBJTYPE_STARTPOS:
2268 {
2269 struct packet_edit_startpos_full *packet = pd.startpos;
2270 const struct startpos *psp = objbind_get_object(ob);
2271
2272 if (NULL != psp) {
2273 startpos_pack(psp, packet);
2274 }
2275 }
2276 return;
2277
2278 case OBJTYPE_UNIT:
2279 {
2280 struct packet_edit_unit *packet = pd.unit;
2281 const struct unit *punit = objbind_get_object(ob);
2282
2283 if (NULL == punit) {
2284 return;
2285 }
2286
2287 packet->id = punit->id;
2288 packet->moves_left = punit->moves_left;
2289 packet->fuel = punit->fuel;
2290 packet->moved = punit->moved;
2291 packet->done_moving = punit->done_moving;
2292 packet->hp = punit->hp;
2293 packet->veteran = punit->veteran;
2294 packet->stay = punit->stay;
2295 /* TODO: Set more packet fields. */
2296 }
2297 return;
2298
2299 case OBJTYPE_CITY:
2300 {
2301 struct packet_edit_city *packet = pd.city;
2302 const struct city *pcity = objbind_get_object(ob);
2303 int i;
2304
2305 if (NULL == pcity) {
2306 return;
2307 }
2308
2309 packet->id = pcity->id;
2310 sz_strlcpy(packet->name, pcity->name);
2311 packet->size = city_size_get(pcity);
2312 packet->history = pcity->history;
2313 for (i = 0; i < B_LAST; i++) {
2314 packet->built[i] = pcity->built[i].turn;
2315 }
2316 packet->food_stock = pcity->food_stock;
2317 packet->shield_stock = pcity->shield_stock;
2318 /* TODO: Set more packet fields. */
2319 }
2320 return;
2321
2322 case OBJTYPE_PLAYER:
2323 {
2324 struct packet_edit_player *packet = pd.player;
2325 const struct player *pplayer = objbind_get_object(ob);
2326 const struct nation_type *pnation;
2327 const struct research *presearch;
2328
2329 if (NULL == pplayer) {
2330 return;
2331 }
2332
2333 packet->id = player_number(pplayer);
2334 sz_strlcpy(packet->name, pplayer->name);
2335 pnation = nation_of_player(pplayer);
2336 packet->nation = nation_index(pnation);
2337 presearch = research_get(pplayer);
2339 packet->inventions[tech]
2342 packet->autoselect_weight = pplayer->autoselect_weight;
2343 packet->gold = pplayer->economic.gold;
2344 packet->infrapoints = pplayer->economic.infra_points;
2345 packet->government = government_index(pplayer->government);
2347 /* TODO: Set more packet fields. */
2348 }
2349 return;
2350
2351 case OBJTYPE_GAME:
2352 {
2353 struct packet_edit_game *packet = pd.game.game;
2354 const struct civ_game *pgame = objbind_get_object(ob);
2355
2356 if (NULL == pgame) {
2357 return;
2358 }
2359
2360 packet->scenario = pgame->scenario.is_scenario;
2361 sz_strlcpy(packet->scenario_name, pgame->scenario.name);
2362 sz_strlcpy(packet->scenario_authors, pgame->scenario.authors);
2363 sz_strlcpy(pd.game.desc->scenario_desc, pgame->scenario_desc.description);
2364 packet->scenario_random = pgame->scenario.save_random;
2365 packet->scenario_players = pgame->scenario.players;
2366 packet->startpos_nations = pgame->scenario.startpos_nations;
2367 packet->prevent_new_cities = pgame->scenario.prevent_new_cities;
2368 packet->lake_flooding = pgame->scenario.lake_flooding;
2369 }
2370 return;
2371
2372 case NUM_OBJTYPES:
2373 break;
2374 }
2375
2376 log_error("%s(): Unhandled object type %s (nb %d).", __FUNCTION__,
2378}
2379
2380/************************************************************************/
2384 struct objprop *op,
2385 union packetdata pd)
2386{
2387 struct propval *pv;
2390
2391 if (!op || !ob || !pd.pointers.v_pointer1) {
2392 return;
2393 }
2394
2395 if (NULL == objbind_get_object(ob)) {
2396 return;
2397 }
2398
2400 return;
2401 }
2402
2404 if (!pv) {
2405 return;
2406 }
2407
2410
2411 switch (objtype) {
2412 case OBJTYPE_TILE:
2413 {
2414 struct packet_edit_tile *packet = pd.tile;
2415
2416 switch (propid) {
2417 case OPID_TILE_SPECIALS:
2419 if (BV_ISSET(pv->data.v_bv_special, pextra->data.special_idx)) {
2420 BV_SET(packet->extras, pextra->data.special_idx);
2421 } else {
2422 BV_CLR(packet->extras, pextra->data.special_idx);
2423 }
2425 return;
2426 case OPID_TILE_ROADS:
2428 int ridx = road_number(extra_road_get(pextra));
2429
2430 if (BV_ISSET(pv->data.v_bv_roads, ridx)) {
2431 BV_SET(packet->extras, extra_index(pextra));
2432 } else {
2433 BV_CLR(packet->extras, extra_index(pextra));
2434 }
2436 return;
2437 case OPID_TILE_BASES:
2439 int bidx = base_number(extra_base_get(pextra));
2440
2441 if (BV_ISSET(pv->data.v_bv_bases, bidx)) {
2442 BV_SET(packet->extras, extra_index(pextra));
2443 } else {
2444 BV_CLR(packet->extras, extra_index(pextra));
2445 }
2447 return;
2448 case OPID_TILE_LABEL:
2449 sz_strlcpy(packet->label, pv->data.v_string);
2450 return;
2451 default:
2452 break;
2453 }
2454 }
2455 log_error("%s(): Unhandled request to pack value of property "
2456 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2458 return;
2459
2460 case OBJTYPE_STARTPOS:
2461 {
2462 struct packet_edit_startpos_full *packet = pd.startpos;
2463
2464 switch (propid) {
2466 packet->exclude = pv->data.v_bool;
2467 return;
2469 BV_CLR_ALL(packet->nations);
2470 nation_hash_iterate(pv->data.v_nation_hash, pnation) {
2471 BV_SET(packet->nations, nation_number(pnation));
2473 return;
2474 default:
2475 break;
2476 }
2477 }
2478 log_error("%s(): Unhandled request to pack value of property "
2479 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2481 return;
2482
2483 case OBJTYPE_UNIT:
2484 {
2485 struct packet_edit_unit *packet = pd.unit;
2486
2487 switch (propid) {
2489 packet->moves_left = pv->data.v_int;
2490 return;
2491 case OPID_UNIT_FUEL:
2492 packet->fuel = pv->data.v_int;
2493 return;
2494 case OPID_UNIT_MOVED:
2495 packet->moved = pv->data.v_bool;
2496 return;
2498 packet->done_moving = pv->data.v_bool;
2499 return;
2500 case OPID_UNIT_HP:
2501 packet->hp = pv->data.v_int;
2502 return;
2503 case OPID_UNIT_VETERAN:
2504 packet->veteran = pv->data.v_int;
2505 return;
2506 case OPID_UNIT_STAY:
2507 packet->stay = pv->data.v_bool;
2508 return;
2509 default:
2510 break;
2511 }
2512 }
2513 log_error("%s(): Unhandled request to pack value of property "
2514 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2516 return;
2517
2518 case OBJTYPE_CITY:
2519 {
2520 struct packet_edit_city *packet = pd.city;
2521
2522 switch (propid) {
2523 case OPID_CITY_NAME:
2524 sz_strlcpy(packet->name, pv->data.v_string);
2525 return;
2526 case OPID_CITY_SIZE:
2527 packet->size = pv->data.v_int;
2528 return;
2529 case OPID_CITY_HISTORY:
2530 packet->history = pv->data.v_int;
2531 return;
2533 packet->food_stock = pv->data.v_int;
2534 return;
2536 packet->shield_stock = pv->data.v_int;
2537 return;
2539 {
2540 int i;
2541
2542 for (i = 0; i < B_LAST; i++) {
2543 packet->built[i] = pv->data.v_built[i].turn;
2544 }
2545 }
2546 return;
2547 default:
2548 break;
2549 }
2550 }
2551 log_error("%s(): Unhandled request to pack value of property "
2552 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2554 return;
2555
2556 case OBJTYPE_PLAYER:
2557 {
2558 struct packet_edit_player *packet = pd.player;
2559
2560 switch (propid) {
2561 case OPID_PLAYER_NAME:
2562 sz_strlcpy(packet->name, pv->data.v_string);
2563 return;
2564 case OPID_PLAYER_NATION:
2565 packet->nation = nation_index(pv->data.v_nation);
2566 return;
2567 case OPID_PLAYER_GOV:
2568 packet->government = government_index(pv->data.v_gov);
2569 return;
2572 packet->inventions[tech] = BV_ISSET(pv->data.v_bv_inventions, tech);
2574 return;
2576 packet->scenario_reserved = pv->data.v_bool;
2577 return;
2579 packet->autoselect_weight = pv->data.v_int;
2580 return;
2582 packet->bulbs_researched = pv->data.v_int;
2583 return;
2584 case OPID_PLAYER_GOLD:
2585 packet->gold = pv->data.v_int;
2586 return;
2588 packet->infrapoints = pv->data.v_int;
2589 return;
2590 default:
2591 break;
2592 }
2593 }
2594 log_error("%s(): Unhandled request to pack value of property "
2595 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2597 return;
2598
2599 case OBJTYPE_GAME:
2600 {
2601 struct packet_edit_game *packet = pd.game.game;
2602
2603 switch (propid) {
2604 case OPID_GAME_SCENARIO:
2605 packet->scenario = pv->data.v_bool;
2606 return;
2608 sz_strlcpy(packet->scenario_name, pv->data.v_const_string);
2609 return;
2611 sz_strlcpy(packet->scenario_authors, pv->data.v_const_string);
2612 return;
2614 sz_strlcpy(pd.game.desc->scenario_desc, pv->data.v_const_string);
2615 return;
2617 packet->scenario_random = pv->data.v_bool;
2618 return;
2620 packet->scenario_players = pv->data.v_bool;
2621 return;
2623 packet->startpos_nations = pv->data.v_bool;
2624 return;
2626 packet->prevent_new_cities = pv->data.v_bool;
2627 return;
2629 packet->lake_flooding = pv->data.v_bool;
2630 return;
2632 packet->ruleset_locked = pv->data.v_bool;
2633 return;
2634 default:
2635 break;
2636 }
2637 }
2638 log_error("%s(): Unhandled request to pack value of property "
2639 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2641 return;
2642
2643 case NUM_OBJTYPES:
2644 break;
2645 }
2646
2647 log_error("%s(): Unhandled request for object type \"%s\" (nb %d).",
2649
2650}
2651
2652/************************************************************************/
2655static void objbind_set_rowref(struct objbind *ob,
2657{
2658 if (!ob) {
2659 return;
2660 }
2661 ob->rowref = rr;
2662}
2663
2664/************************************************************************/
2668{
2669 if (!ob) {
2670 return NULL;
2671 }
2672 return ob->rowref;
2673}
2674
2675/************************************************************************/
2678static int objprop_get_id(const struct objprop *op)
2679{
2680 if (!op) {
2681 return -1;
2682 }
2683 return op->id;
2684}
2685
2686/************************************************************************/
2693static GType objprop_get_gtype(const struct objprop *op)
2694{
2696
2697 switch (op->valtype) {
2698 case VALTYPE_NONE:
2700 return G_TYPE_NONE;
2701 case VALTYPE_INT:
2702 return G_TYPE_INT;
2703 case VALTYPE_BOOL:
2704 /* We want to show it as translated string, not as untranslated G_TYPE_BOOLEAN */
2705 return G_TYPE_STRING;
2706 case VALTYPE_STRING:
2709 case VALTYPE_BV_SPECIAL:
2710 case VALTYPE_BV_ROADS:
2711 case VALTYPE_BV_BASES:
2713 return G_TYPE_STRING;
2714 case VALTYPE_PIXBUF:
2715 case VALTYPE_NATION:
2716 case VALTYPE_GOV:
2717 return GDK_TYPE_PIXBUF;
2718 }
2719 log_error("%s(): Unhandled value type %d.", __FUNCTION__, op->valtype);
2720 return G_TYPE_NONE;
2721}
2722
2723/************************************************************************/
2726static enum value_types objprop_get_valtype(const struct objprop *op)
2727{
2728 if (!op) {
2729 return VALTYPE_NONE;
2730 }
2731 return op->valtype;
2732}
2733
2734/************************************************************************/
2737static bool objprop_show_in_listview(const struct objprop *op)
2738{
2739 if (!op) {
2740 return FALSE;
2741 }
2742 return op->flags & OPF_IN_LISTVIEW;
2743}
2744
2745/************************************************************************/
2748static bool objprop_has_widget(const struct objprop *op)
2749{
2750 if (!op) {
2751 return FALSE;
2752 }
2753 return op->flags & OPF_HAS_WIDGET;
2754}
2755
2756/************************************************************************/
2762static const char *objprop_get_attribute_type_string(const struct objprop *op)
2763{
2764 GType gtype;
2765
2766 if (!op) {
2767 return NULL;
2768 }
2769
2771 if (gtype == G_TYPE_INT || gtype == G_TYPE_STRING
2772 || gtype == G_TYPE_BOOLEAN) {
2773 return "text";
2774 } else if (gtype == GDK_TYPE_PIXBUF) {
2775 return "pixbuf";
2776 }
2777
2778 return NULL;
2779}
2780
2781/************************************************************************/
2787static void objprop_set_column_id(struct objprop *op, int col_id)
2788{
2789 if (!op) {
2790 return;
2791 }
2792 op->column_id = col_id;
2793}
2794
2795/************************************************************************/
2800static int objprop_get_column_id(const struct objprop *op)
2801{
2802 if (!op) {
2803 return -1;
2804 }
2805 return op->column_id;
2806}
2807
2808/************************************************************************/
2813{
2814 if (!op) {
2815 return;
2816 }
2817 op->view_column = col;
2818}
2819
2820/************************************************************************/
2825{
2826 if (!op) {
2827 return NULL;
2828 }
2829 return op->view_column;
2830}
2831
2832/************************************************************************/
2835static const char *objprop_get_name(const struct objprop *op)
2836{
2837 if (!op) {
2838 return NULL;
2839 }
2840 return op->name;
2841}
2842
2843/************************************************************************/
2846static const char *objprop_get_tooltip(const struct objprop *op)
2847{
2848 if (!op) {
2849 return NULL;
2850 }
2851 return op->tooltip;
2852}
2853
2854/************************************************************************/
2860{
2862 GType gtype;
2863
2865
2866 if (gtype == G_TYPE_INT || gtype == G_TYPE_STRING
2867 || gtype == G_TYPE_BOOLEAN) {
2869 } else if (gtype == GDK_TYPE_PIXBUF) {
2871 }
2872
2873 return cell;
2874}
2875
2876/************************************************************************/
2880static bool objprop_is_sortable(const struct objprop *op)
2881{
2882 GType gtype;
2883 if (!op) {
2884 return FALSE;
2885 }
2887 return gtype == G_TYPE_INT || gtype == G_TYPE_STRING;
2888}
2889
2890/************************************************************************/
2894static bool objprop_is_readonly(const struct objprop *op)
2895{
2896 if (!op) {
2897 return TRUE;
2898 }
2899 return !(op->flags & OPF_EDITABLE);
2900}
2901
2902/************************************************************************/
2906{
2907 struct objprop *op;
2908 struct property_page *pp;
2909 struct propval value = {{0,}, VALTYPE_STRING, FALSE};
2910
2911 op = userdata;
2914
2916}
2917
2918/************************************************************************/
2923{
2924 struct objprop *op;
2925 struct property_page *pp;
2926 struct propval value = {{0,}, VALTYPE_INT, FALSE};
2927
2928 op = userdata;
2931
2933}
2934
2935/************************************************************************/
2940{
2941 struct objprop *op;
2942 struct property_page *pp;
2943 struct propval value = {{0,}, VALTYPE_BOOL, FALSE};
2944
2945 op = userdata;
2948
2950}
2951
2952/************************************************************************/
2955static void objprop_setup_widget(struct objprop *op)
2956{
2957 GtkWidget *hbox, *hbox2, *label, *image, *text, *spin, *button;
2958 struct extviewer *ev = NULL;
2960
2961 if (!op) {
2962 return;
2963 }
2964
2965 if (!objprop_has_widget(op)) {
2966 return;
2967 }
2968
2970 op->widget = hbox;
2971
2975 gtk_box_append(GTK_BOX(hbox), label);
2976 objprop_set_child_widget(op, "name-label", label);
2977
2979
2980 switch (propid) {
2981 case OPID_TILE_INDEX:
2982 case OPID_TILE_X:
2983 case OPID_TILE_Y:
2984 case OPID_TILE_NAT_X:
2985 case OPID_TILE_NAT_Y:
2987 case OPID_TILE_TERRAIN:
2988 case OPID_TILE_RESOURCE:
2989 case OPID_TILE_XY:
2990 case OPID_STARTPOS_XY:
2991 case OPID_UNIT_ID:
2992 case OPID_UNIT_XY:
2993 case OPID_UNIT_TYPE:
2994 case OPID_CITY_ID:
2995 case OPID_CITY_XY:
2996 case OPID_PLAYER_AGE:
2997#ifdef FREECIV_DEBUG
2998 case OPID_TILE_ADDRESS:
2999 case OPID_UNIT_ADDRESS:
3000 case OPID_CITY_ADDRESS:
3002#endif /* FREECIV_DEBUG */
3003 label = gtk_label_new(NULL);
3007 gtk_box_append(GTK_BOX(hbox), label);
3008 objprop_set_child_widget(op, "value-label", label);
3009 return;
3010
3011 case OPID_TILE_IMAGE:
3013 case OPID_UNIT_IMAGE:
3014 case OPID_CITY_IMAGE:
3015 image = gtk_image_new();
3024 return;
3025
3026 case OPID_CITY_NAME:
3027 case OPID_PLAYER_NAME:
3029 case OPID_TILE_LABEL:
3030 text = gtk_text_new();
3034 g_signal_connect(text, "changed",
3036 gtk_box_append(GTK_BOX(hbox), text);
3037 objprop_set_child_widget(op, "text", text);
3038 return;
3039
3041 case OPID_CITY_SIZE:
3042 case OPID_CITY_HISTORY:
3046 case OPID_PLAYER_GOLD:
3048 spin = gtk_spin_button_new_with_range(0.0, 100.0, 1.0);
3051 g_signal_connect(spin, "value-changed",
3055 return;
3056
3057 case OPID_UNIT_FUEL:
3058 case OPID_UNIT_HP:
3059 case OPID_UNIT_VETERAN:
3065 spin = gtk_spin_button_new_with_range(0.0, 100.0, 1.0);
3066 g_signal_connect(spin, "value-changed",
3070 label = gtk_label_new(NULL);
3073 gtk_box_append(GTK_BOX(hbox2), label);
3074 objprop_set_child_widget(op, "max-value-label", label);
3075 return;
3076
3077 case OPID_TILE_SPECIALS:
3078 case OPID_TILE_ROADS:
3079 case OPID_TILE_BASES:
3080 case OPID_TILE_VISION:
3083 case OPID_PLAYER_NATION:
3084 case OPID_PLAYER_GOV:
3088 ev = extviewer_new(op);
3094 return;
3095
3097 case OPID_UNIT_MOVED:
3099 case OPID_UNIT_STAY:
3100 case OPID_GAME_SCENARIO:
3108 button = gtk_toggle_button_new();
3111 g_signal_connect(button, "toggled",
3113 op);
3114 gtk_box_append(GTK_BOX(hbox), button);
3115 objprop_set_child_widget(op, "togglebutton", button);
3116 return;
3117 }
3118
3119 log_error("%s(): Unhandled request to create widget for property %d (%s).",
3121}
3122
3123/************************************************************************/
3132 struct objbind *ob)
3133{
3134 GtkWidget *w, *label, *image, *text, *spin, *button;
3135 struct extviewer *ev;
3136 struct propval *pv;
3137 bool modified;
3139 double min, max, step, big_step;
3140 char buf[256];
3141 const char *newtext;
3142 GtkEntryBuffer *buffer;
3143
3144 if (!op || !objprop_has_widget(op)) {
3145 return;
3146 }
3147
3149 if (!w) {
3150 return;
3151 }
3152
3154
3155 /* NB: We must take care to propval_free() the return value of
3156 * objbind_get_value_from_object(), since it always makes a
3157 * copy, but to NOT free the result of objbind_get_modified_value()
3158 * since it returns its own stored value. */
3161
3162 if (pv && modified) {
3163 struct propval *pv_mod;
3164
3166 if (pv_mod) {
3167 if (propval_equal(pv, pv_mod)) {
3169 modified = FALSE;
3170 } else {
3172 pv = pv_mod;
3173 modified = TRUE;
3174 }
3175 } else {
3176 modified = FALSE;
3177 }
3178 }
3179
3180 switch (propid) {
3181 case OPID_TILE_IMAGE:
3183 case OPID_UNIT_IMAGE:
3184 case OPID_CITY_IMAGE:
3185 image = objprop_get_child_widget(op, "image");
3186 if (pv) {
3187 gtk_image_set_from_pixbuf(GTK_IMAGE(image), pv->data.v_pixbuf);
3188 } else {
3190 }
3191 break;
3192
3193 case OPID_TILE_XY:
3194 case OPID_TILE_TERRAIN:
3195 case OPID_TILE_RESOURCE:
3196 case OPID_STARTPOS_XY:
3197 case OPID_UNIT_XY:
3198 case OPID_UNIT_TYPE:
3199 case OPID_CITY_XY:
3200#ifdef FREECIV_DEBUG
3201 case OPID_TILE_ADDRESS:
3202 case OPID_UNIT_ADDRESS:
3203 case OPID_CITY_ADDRESS:
3205#endif /* FREECIV_DEBUG */
3206 label = objprop_get_child_widget(op, "value-label");
3207 if (pv) {
3208 gtk_label_set_text(GTK_LABEL(label), pv->data.v_string);
3209 } else {
3211 }
3212 break;
3213
3214 case OPID_TILE_INDEX:
3215 case OPID_TILE_X:
3216 case OPID_TILE_Y:
3217 case OPID_TILE_NAT_X:
3218 case OPID_TILE_NAT_Y:
3220 case OPID_UNIT_ID:
3221 case OPID_CITY_ID:
3222 case OPID_PLAYER_AGE:
3223 label = objprop_get_child_widget(op, "value-label");
3224 if (pv) {
3225 char agebuf[16];
3226
3227 fc_snprintf(agebuf, sizeof(agebuf), "%d", pv->data.v_int);
3229 } else {
3231 }
3232 break;
3233
3234 case OPID_CITY_NAME:
3235 case OPID_PLAYER_NAME:
3237 case OPID_TILE_LABEL:
3238 text = objprop_get_child_widget(op, "text");
3239 if (pv) {
3240 /* Most of these are semantically in "v_const_string",
3241 * but this works as the address is the same regardless. */
3242 newtext = pv->data.v_string;
3243 } else {
3244 newtext = "";
3245 }
3246 buffer = gtk_text_get_buffer(GTK_TEXT(text));
3247
3248 /* Only set the text if it has changed. This breaks
3249 * recursive loop. */
3252 }
3254 break;
3255
3257 case OPID_CITY_SIZE:
3258 case OPID_CITY_HISTORY:
3262 case OPID_PLAYER_GOLD:
3264 spin = objprop_get_child_widget(op, "spin");
3265 if (pv) {
3268 if (objbind_get_allowed_value_span(ob, op, &min, &max,
3269 &step, &big_step)) {
3272 step, big_step);
3273 }
3277 }
3279 break;
3280
3281 case OPID_UNIT_FUEL:
3282 case OPID_UNIT_HP:
3283 case OPID_UNIT_VETERAN:
3285 spin = objprop_get_child_widget(op, "spin");
3286 label = objprop_get_child_widget(op, "max-value-label");
3287 if (pv) {
3290 if (objbind_get_allowed_value_span(ob, op, &min, &max,
3291 &step, &big_step)) {
3294 step, big_step);
3295 fc_snprintf(buf, sizeof(buf), "/%d", (int) max);
3297 } else {
3299 }
3303 } else {
3305 }
3307 break;
3308
3309 case OPID_TILE_SPECIALS:
3310 case OPID_TILE_ROADS:
3311 case OPID_TILE_BASES:
3312 case OPID_TILE_VISION:
3315 case OPID_PLAYER_NATION:
3316 case OPID_PLAYER_GOV:
3321 if (pv) {
3323 } else {
3325 }
3326 break;
3327
3329 case OPID_UNIT_MOVED:
3331 case OPID_UNIT_STAY:
3332 case OPID_GAME_SCENARIO:
3340 button = objprop_get_child_widget(op, "togglebutton");
3343 if (pv) {
3345 pv->data.v_bool);
3346 } else {
3348 }
3351 gtk_widget_set_sensitive(button, pv != NULL);
3352 break;
3353 }
3354
3355 if (!modified) {
3357 }
3358
3359 label = objprop_get_child_widget(op, "name-label");
3360 if (label) {
3361 const char *name = objprop_get_name(op);
3362 if (modified) {
3363 char namebuf[128];
3364
3365 fc_snprintf(namebuf, sizeof(namebuf),
3366 "<span foreground=\"red\">%s</span>", name);
3368 } else {
3370 }
3371 }
3372}
3373
3374/************************************************************************/
3379{
3380 if (!op) {
3381 return NULL;
3382 }
3383 if (!op->widget) {
3385 }
3386 return op->widget;
3387}
3388
3389/************************************************************************/
3394 const char *widget_name,
3396{
3397 GtkWidget *w;
3398
3399 if (!op || !widget_name || !widget) {
3400 return;
3401 }
3402
3404 if (!w) {
3405 log_error("Cannot store child widget %p under name "
3406 "\"%s\" using objprop_set_child_widget for object "
3407 "property %d (%s) because objprop_get_widget does "
3408 "not return a valid widget.",
3410 return;
3411 }
3412
3414}
3415
3416/************************************************************************/
3421 const char *widget_name)
3422{
3423 GtkWidget *w, *child;
3424
3425 if (!op || !widget_name) {
3426 return NULL;
3427 }
3428
3430 if (!w) {
3431 log_error("Cannot retrieve child widget under name "
3432 "\"%s\" using objprop_get_child_widget for object "
3433 "property %d (%s) because objprop_get_widget does "
3434 "not return a valid widget.",
3436 return NULL;
3437 }
3438
3440 if (!child) {
3441 log_error("Child widget \"%s\" not found for object "
3442 "property %d (%s) via objprop_get_child_widget.",
3444 return NULL;
3445 }
3446
3447 return child;
3448}
3449
3450/************************************************************************/
3454 struct extviewer *ev)
3455{
3456 if (!op) {
3457 return;
3458 }
3459 op->extviewer = ev;
3460}
3461
3462/************************************************************************/
3466{
3467 if (!op) {
3468 return NULL;
3469 }
3470 return op->extviewer;
3471}
3472
3473/************************************************************************/
3477{
3478 if (!op) {
3479 return NULL;
3480 }
3481 return op->parent_page;
3482}
3483
3484/************************************************************************/
3487static struct objprop *objprop_new(int id,
3488 const char *name,
3489 const char *tooltip,
3491 enum value_types valtype,
3492 struct property_page *parent)
3493{
3494 struct objprop *op;
3495
3496 op = fc_calloc(1, sizeof(*op));
3497 op->id = id;
3498 op->name = name;
3499 op->tooltip = tooltip;
3500 op->flags = flags;
3501 op->valtype = valtype;
3502 op->column_id = -1;
3503 op->parent_page = parent;
3504
3505 return op;
3506}
3507
3508/************************************************************************/
3512static struct extviewer *extviewer_new(struct objprop *op)
3513{
3514 struct extviewer *ev;
3515 GtkWidget *hbox, *vbox, *label, *button, *scrollwin, *image;
3516 GtkWidget *view = NULL;
3520 GType *gtypes;
3522 int num_cols;
3523
3524 if (!op) {
3525 return NULL;
3526 }
3527
3528 ev = fc_calloc(1, sizeof(*ev));
3529 ev->objprop = op;
3530
3532
3533
3534 /* Create the panel widget. */
3535
3536 switch (propid) {
3537 case OPID_TILE_SPECIALS:
3538 case OPID_TILE_ROADS:
3539 case OPID_TILE_BASES:
3546 ev->panel_widget = hbox;
3547
3548 label = gtk_label_new(NULL);
3551 gtk_box_append(GTK_BOX(hbox), label);
3552 ev->panel_label = label;
3553 break;
3554
3555 case OPID_PLAYER_NATION:
3556 case OPID_PLAYER_GOV:
3558 ev->panel_widget = vbox;
3559
3560 label = gtk_label_new(NULL);
3563 gtk_box_append(GTK_BOX(vbox), label);
3564 ev->panel_label = label;
3565
3567 gtk_box_append(GTK_BOX(vbox), hbox);
3568
3569 image = gtk_image_new();
3570 if (propid == OPID_PLAYER_GOV) {
3574 } else {
3575 /* propid OPID_PLAYER_NATION */
3577 }
3581 ev->panel_image = image;
3582 break;
3583
3584 case OPID_TILE_VISION:
3586 ev->panel_widget = hbox;
3587 break;
3588
3589 default:
3590 log_error("Unhandled request to create panel widget "
3591 "for property %d (%s) in extviewer_new().",
3594 ev->panel_widget = hbox;
3595 break;
3596 }
3597
3598 if (objprop_is_readonly(op)) {
3599 button = gtk_button_new_with_label(Q_("?verb:View"));
3600 } else {
3601 button = gtk_button_new_with_label(_("Edit"));
3602 }
3603 g_signal_connect(button, "clicked",
3605 gtk_box_append(GTK_BOX(hbox), button);
3606 ev->panel_button = button;
3607
3608
3609 /* Create the data store. */
3610
3611 switch (propid) {
3612 case OPID_TILE_SPECIALS:
3613 case OPID_TILE_ROADS:
3614 case OPID_TILE_BASES:
3618 break;
3619 case OPID_TILE_VISION:
3620 num_cols = 3 + 1 + V_COUNT;
3621 gtypes = fc_malloc(num_cols * sizeof(GType));
3622 gtypes[0] = G_TYPE_INT; /* player number */
3623 gtypes[1] = GDK_TYPE_PIXBUF; /* player flag */
3624 gtypes[2] = G_TYPE_STRING; /* player name */
3625 gtypes[3] = G_TYPE_BOOLEAN; /* tile_known */
3627 gtypes[4 + v] = G_TYPE_BOOLEAN; /* tile_seen[v] */
3630 free(gtypes);
3631 break;
3635 break;
3637 case OPID_PLAYER_NATION:
3638 case OPID_PLAYER_GOV:
3641 break;
3645 break;
3646 default:
3647 log_error("Unhandled request to create data store "
3648 "for property %d (%s) in extviewer_new().",
3650 break;
3651 }
3652
3653 ev->store = store;
3654 ev->textbuf = textbuf;
3655
3656 /* Create the view widget. */
3657
3659 ev->view_widget = vbox;
3660
3664 gtk_box_append(GTK_BOX(vbox), label);
3665 ev->view_label = label;
3666
3667 if (store || textbuf) {
3670 TRUE);
3675
3676 if (store) {
3680 } else {
3681 const bool editable = !objprop_is_readonly(op);
3682
3686 }
3689 gtk_widget_add_css_class(GTK_WIDGET(view), "large-pixbufs");
3690
3692 }
3693
3694 switch (propid) {
3695
3696 case OPID_TILE_SPECIALS:
3697 case OPID_TILE_ROADS:
3698 case OPID_TILE_BASES:
3699 /* TRANS: As in "this tile special is present". */
3700 add_column(view, 0, _("Present"), G_TYPE_BOOLEAN, TRUE, FALSE,
3702 add_column(view, 1, _("ID"), G_TYPE_INT,
3703 FALSE, FALSE, NULL, NULL);
3704 add_column(view, 2, _("Name"), G_TYPE_STRING,
3705 FALSE, FALSE, NULL, NULL);
3706 break;
3707
3708 case OPID_TILE_VISION:
3709 add_column(view, 0, _("ID"), G_TYPE_INT,
3710 FALSE, FALSE, NULL, NULL);
3711 add_column(view, 1, _("Nation"), GDK_TYPE_PIXBUF,
3712 FALSE, FALSE, NULL, NULL);
3713 add_column(view, 2, _("Name"), G_TYPE_STRING,
3714 FALSE, FALSE, NULL, NULL);
3715 add_column(view, 3, _("Known"), G_TYPE_BOOLEAN,
3716 FALSE, FALSE, NULL, NULL);
3721 break;
3722
3724 /* TRANS: As in "this building is present". */
3725 add_column(view, 0, _("Present"), G_TYPE_BOOLEAN, TRUE, FALSE,
3727 add_column(view, 1, _("ID"), G_TYPE_INT,
3728 FALSE, FALSE, NULL, NULL);
3729 add_column(view, 2, _("Name"), G_TYPE_STRING,
3730 FALSE, FALSE, NULL, NULL);
3731 /* TRANS: As in "the turn when this building was built". */
3732 add_column(view, 3, _("Turn Built"), G_TYPE_STRING,
3733 FALSE, FALSE, NULL, NULL);
3734 break;
3735
3737 /* TRANS: As in "the player has set this nation". */
3738 add_column(view, 0, _("Set"), G_TYPE_BOOLEAN, TRUE, FALSE,
3740 add_column(view, 1, _("ID"), G_TYPE_INT,
3741 FALSE, FALSE, NULL, NULL);
3742 add_column(view, 2, _("Flag"), GDK_TYPE_PIXBUF,
3743 FALSE, FALSE, NULL, NULL);
3744 add_column(view, 3, _("Name"), G_TYPE_STRING,
3745 FALSE, FALSE, NULL, NULL);
3746 break;
3747
3748 case OPID_PLAYER_NATION:
3749 case OPID_PLAYER_GOV:
3750 /* TRANS: As in "the player has set this nation". */
3751 add_column(view, 0, _("Set"), G_TYPE_BOOLEAN, TRUE, TRUE,
3753 add_column(view, 1, _("ID"), G_TYPE_INT,
3754 FALSE, FALSE, NULL, NULL);
3755 add_column(view, 2,
3756 propid == OPID_PLAYER_GOV ? _("Icon") : _("Flag"),
3758 FALSE, FALSE, NULL, NULL);
3759 add_column(view, 3, _("Name"), G_TYPE_STRING,
3760 FALSE, FALSE, NULL, NULL);
3761 break;
3762
3764 /* TRANS: As in "this invention is known". */
3765 add_column(view, 0, _("Known"), G_TYPE_BOOLEAN, TRUE, FALSE,
3767 add_column(view, 1, _("ID"), G_TYPE_INT,
3768 FALSE, FALSE, NULL, NULL);
3769 add_column(view, 2, _("Name"), G_TYPE_STRING,
3770 FALSE, FALSE, NULL, NULL);
3771 break;
3772
3775 g_signal_connect(textbuf, "changed",
3777 break;
3778
3779 default:
3780 log_error("Unhandled request to configure view widget "
3781 "for property %d (%s) in extviewer_new().",
3783 break;
3784 }
3785
3786 gtk_widget_set_visible(ev->panel_widget, TRUE);
3787 gtk_widget_set_visible(ev->view_widget, TRUE);
3788
3789 return ev;
3790}
3791
3792/************************************************************************/
3796{
3797 if (!ev) {
3798 return NULL;
3799 }
3800 return ev->objprop;
3801}
3802
3803/************************************************************************/
3808{
3809 if (!ev) {
3810 return NULL;
3811 }
3812 return ev->panel_widget;
3813}
3814
3815/************************************************************************/
3820{
3821 if (!ev) {
3822 return NULL;
3823 }
3824 return ev->view_widget;
3825}
3826
3827/************************************************************************/
3831 struct propval *pv)
3832{
3833 struct objprop *op;
3835 int id, turn_built;
3836 bool present, all;
3837 const char *name;
3839 GtkListStore *store;
3840 GtkTextBuffer *textbuf;
3842 gchar *buf;
3843
3844 if (!ev) {
3845 return;
3846 }
3847
3850
3851 if (propval_equal(pv, ev->pv_cached)) {
3852 return;
3853 }
3854 propval_free(ev->pv_cached);
3855 ev->pv_cached = propval_copy(pv);
3856 store = ev->store;
3857 textbuf = ev->textbuf;
3858
3859
3860 /* NB: Remember to have -1 as the last argument to
3861 * gtk_list_store_set() and to use the correct column
3862 * number when inserting data. :) */
3863 switch (propid) {
3864
3865 case OPID_TILE_SPECIALS:
3866 gtk_list_store_clear(store);
3868 id = spe->data.special_idx;
3870 present = BV_ISSET(pv->data.v_bv_special, id);
3871 gtk_list_store_append(store, &iter);
3872 gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name, -1);
3875 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
3876 g_free(buf);
3877 break;
3878
3879 case OPID_TILE_ROADS:
3880 gtk_list_store_clear(store);
3882 struct road_type *proad = extra_road_get(pextra);
3883
3884 id = road_number(proad);
3885 name = extra_name_translation(pextra);
3886 present = BV_ISSET(pv->data.v_bv_roads, id);
3887 gtk_list_store_append(store, &iter);
3888 gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name, -1);
3891 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
3892 g_free(buf);
3893 break;
3894
3895 case OPID_TILE_BASES:
3896 gtk_list_store_clear(store);
3898 struct base_type *pbase = extra_base_get(pextra);
3899
3900 id = base_number(pbase);
3901 name = extra_name_translation(pextra);
3902 present = BV_ISSET(pv->data.v_bv_bases, id);
3903 gtk_list_store_append(store, &iter);
3904 gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name, -1);
3907 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
3908 g_free(buf);
3909 break;
3910
3911 case OPID_TILE_VISION:
3912 gtk_list_store_clear(store);
3913 player_slots_iterate(pslot) {
3914 id = player_slot_index(pslot);
3915 if (player_slot_is_used(pslot)) {
3916 struct player *pplayer = player_slot_get_player(pslot);
3917
3918 name = player_name(pplayer);
3919 pixbuf = get_flag(pplayer->nation);
3920 } else {
3921 name = "";
3922 pixbuf = NULL;
3923 }
3924 gtk_list_store_append(store, &iter);
3925 gtk_list_store_set(store, &iter, 0, id, 2, name, -1);
3926 if (pixbuf) {
3927 gtk_list_store_set(store, &iter, 1, pixbuf, -1);
3929 pixbuf = NULL;
3930 }
3931 present = BV_ISSET(pv->data.v_tile_vision->tile_known, id);
3932 gtk_list_store_set(store, &iter, 3, present, -1);
3934 present = BV_ISSET(pv->data.v_tile_vision->tile_seen[v], id);
3935 gtk_list_store_set(store, &iter, 4 + v, present, -1);
3938 break;
3939
3941 gtk_list_store_clear(store);
3942 gtk_list_store_append(store, &iter);
3943 all = (0 == nation_hash_size(pv->data.v_nation_hash));
3944 gtk_list_store_set(store, &iter, 0, all, 1, -1, 3,
3945 _("All nations"), -1);
3946 nations_iterate(pnation) {
3948 && is_nation_playable(pnation)) {
3949 present = (!all && nation_hash_lookup(pv->data.v_nation_hash,
3950 pnation, NULL));
3951 id = nation_number(pnation);
3952 pixbuf = get_flag(pnation);
3954 gtk_list_store_append(store, &iter);
3955 gtk_list_store_set(store, &iter, 0, present, 1, id,
3956 2, pixbuf, 3, name, -1);
3957 if (pixbuf) {
3959 }
3960 }
3963 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
3964 g_free(buf);
3965 break;
3966
3968 gtk_list_store_clear(store);
3969 improvement_iterate(pimprove) {
3970 if (is_special_improvement(pimprove)) {
3971 continue;
3972 }
3973 id = improvement_index(pimprove);
3975 turn_built = pv->data.v_built[id].turn;
3976 present = turn_built >= 0;
3977 buf = built_status_to_string(&pv->data.v_built[id]);
3978 gtk_list_store_append(store, &iter);
3979 gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name,
3980 3, buf, -1);
3981 g_free(buf);
3984 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
3985 g_free(buf);
3986 break;
3987
3988 case OPID_PLAYER_NATION:
3989 {
3990 enum barbarian_type barbarian_type
3991 = nation_barbarian_type(pv->data.v_nation);
3992
3993 gtk_list_store_clear(store);
3994 nations_iterate(pnation) {
3996 && nation_barbarian_type(pnation) == barbarian_type
3997 && (barbarian_type != NOT_A_BARBARIAN
3998 || is_nation_playable(pnation))) {
3999 present = (pnation == pv->data.v_nation);
4000 id = nation_index(pnation);
4001 pixbuf = get_flag(pnation);
4003 gtk_list_store_append(store, &iter);
4004 gtk_list_store_set(store, &iter, 0, present, 1, id,
4005 2, pixbuf, 3, name, -1);
4006 if (pixbuf) {
4008 }
4009 }
4011 gtk_label_set_text(GTK_LABEL(ev->panel_label),
4012 nation_adjective_translation(pv->data.v_nation));
4013 pixbuf = get_flag(pv->data.v_nation);
4015 if (pixbuf) {
4017 }
4018 }
4019 break;
4020
4021 case OPID_PLAYER_GOV:
4022 {
4023 gtk_list_store_clear(store);
4025 present = (pgov == pv->data.v_gov);
4026 id = government_index(pgov);
4029 gtk_list_store_append(store, &iter);
4030 gtk_list_store_set(store, &iter, 0, present, 1, id,
4031 2, pixbuf, 3, name, -1);
4032 if (pixbuf) {
4034 }
4036 if (pv->data.v_gov != NULL) {
4037 gtk_label_set_text(GTK_LABEL(ev->panel_label),
4038 government_name_translation(pv->data.v_gov));
4040 } else {
4041 gtk_label_set_text(GTK_LABEL(ev->panel_label), "?");
4044 }
4045
4047 if (pixbuf) {
4049 }
4050 }
4051 break;
4052
4054 gtk_list_store_clear(store);
4056 id = advance_index(padvance);
4057 present = BV_ISSET(pv->data.v_bv_inventions, id);
4059 gtk_list_store_append(store, &iter);
4060 gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name, -1);
4063 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4064 g_free(buf);
4065 break;
4066
4071 {
4072 GtkTextIter start, end;
4073 char *oldtext;
4074
4075 /* Don't re-set content if unchanged, to avoid moving cursor */
4076 gtk_text_buffer_get_bounds(textbuf, &start, &end);
4077 oldtext = gtk_text_buffer_get_text(textbuf, &start, &end, TRUE);
4078 if (strcmp(oldtext, pv->data.v_const_string) != 0) {
4079 gtk_text_buffer_set_text(textbuf, pv->data.v_const_string, -1);
4080 }
4081 }
4084 gtk_widget_set_sensitive(ev->view_widget, TRUE);
4086 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4087 g_free(buf);
4088 break;
4089
4090 default:
4091 log_error("Unhandled request to refresh widgets "
4092 "extviewer_refresh_widgets() for objprop id=%d "
4093 "name \"%s\".", propid, objprop_get_name(op));
4094 break;
4095 }
4096}
4097
4098/************************************************************************/
4102{
4103 struct objprop *op;
4105
4106 if (!ev) {
4107 return;
4108 }
4109
4112
4113 propval_free(ev->pv_cached);
4114 ev->pv_cached = NULL;
4115
4116 if (ev->panel_label != NULL) {
4117 gtk_label_set_text(GTK_LABEL(ev->panel_label), NULL);
4118 }
4119
4120 switch (propid) {
4121 case OPID_TILE_SPECIALS:
4122 case OPID_TILE_ROADS:
4123 case OPID_TILE_BASES:
4124 case OPID_TILE_VISION:
4128 gtk_list_store_clear(ev->store);
4129 break;
4130 case OPID_PLAYER_NATION:
4131 case OPID_PLAYER_GOV:
4132 gtk_list_store_clear(ev->store);
4134 break;
4139 gtk_text_buffer_set_text(ev->textbuf, "", -1);
4142 gtk_widget_set_sensitive(ev->view_widget, FALSE);
4143 break;
4144 default:
4145 log_error("Unhandled request to clear widgets "
4146 "in extviewer_clear_widgets() for objprop id=%d "
4147 "name \"%s\".", propid, objprop_get_name(op));
4148 break;
4149 }
4150}
4151
4152/************************************************************************/
4158{
4159 struct extviewer *ev;
4160 struct property_page *pp;
4161 struct objprop *op;
4162
4163 ev = userdata;
4164 if (!ev) {
4165 return;
4166 }
4167
4171}
4172
4173/************************************************************************/
4177 gchar *path,
4179{
4180 struct extviewer *ev;
4181 struct objprop *op;
4182 struct property_page *pp;
4184 GtkTreeModel *model;
4186 int id, old_id, turn_built;
4187 struct propval *pv;
4188 bool active, present;
4189 gchar *buf;
4191
4192 ev = userdata;
4193 if (!ev) {
4194 return;
4195 }
4196
4197 pv = ev->pv_cached;
4198 if (!pv) {
4199 return;
4200 }
4201
4206
4207 model = GTK_TREE_MODEL(ev->store);
4208 if (!gtk_tree_model_get_iter_from_string(model, &iter, path)) {
4209 return;
4210 }
4211 present = !active;
4212
4213
4214 switch (propid) {
4215
4216 case OPID_TILE_SPECIALS:
4217 gtk_tree_model_get(model, &iter, 1, &id, -1);
4219 return;
4220 }
4221 if (present) {
4222 BV_SET(pv->data.v_bv_special, id);
4223 } else {
4224 BV_CLR(pv->data.v_bv_special, id);
4225 }
4226 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4228 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4229 g_free(buf);
4230 break;
4231
4232 case OPID_TILE_ROADS:
4233 gtk_tree_model_get(model, &iter, 1, &id, -1);
4234 if (!(0 <= id && id < road_count())) {
4235 return;
4236 }
4237 if (present) {
4238 BV_SET(pv->data.v_bv_roads, id);
4239 } else {
4240 BV_CLR(pv->data.v_bv_roads, id);
4241 }
4242 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4244 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4245 g_free(buf);
4246 break;
4247
4248 case OPID_TILE_BASES:
4249 gtk_tree_model_get(model, &iter, 1, &id, -1);
4250 if (!(0 <= id && id < base_count())) {
4251 return;
4252 }
4253 if (present) {
4254 BV_SET(pv->data.v_bv_bases, id);
4255 } else {
4256 BV_CLR(pv->data.v_bv_bases, id);
4257 }
4258 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4260 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4261 g_free(buf);
4262 break;
4263
4265 gtk_tree_model_get(model, &iter, 1, &id, -1);
4266 if (-1 > id && id >= nation_count()) {
4267 return;
4268 }
4269
4270 if (-1 == id) {
4271 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4273 if (present) {
4274 while (gtk_tree_model_iter_next(model, &iter)) {
4275 gtk_list_store_set(ev->store, &iter, 0, FALSE, -1);
4276 }
4277 nation_hash_clear(pv->data.v_nation_hash);
4278 } else {
4279 const struct nation_type *pnation;
4280 int id2;
4281
4283 gtk_tree_model_get(model, &iter, 0, &id2, -1);
4284 gtk_list_store_set(ev->store, &iter, 0, TRUE, -1);
4285 pnation = nation_by_number(id2);
4286 nation_hash_insert(pv->data.v_nation_hash, pnation, NULL);
4287 }
4288 } else {
4289 const struct nation_type *pnation;
4290 bool all;
4291
4292 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4293 pnation = nation_by_number(id);
4294 if (present) {
4295 nation_hash_insert(pv->data.v_nation_hash, pnation, NULL);
4296 } else {
4297 nation_hash_remove(pv->data.v_nation_hash, pnation);
4298 }
4300 all = (0 == nation_hash_size(pv->data.v_nation_hash));
4301 gtk_list_store_set(ev->store, &iter, 0, all, -1);
4302 }
4304 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4305 g_free(buf);
4306 break;
4307
4309 gtk_tree_model_get(model, &iter, 1, &id, -1);
4310 if (!(0 <= id && id < B_LAST)) {
4311 return;
4312 }
4313 turn_built = present ? game.info.turn : I_NEVER;
4314 pv->data.v_built[id].turn = turn_built;
4315 buf = built_status_to_string(&pv->data.v_built[id]);
4316 gtk_list_store_set(ev->store, &iter, 0, present, 3, buf, -1);
4317 g_free(buf);
4319 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4320 g_free(buf);
4321 break;
4322
4323 case OPID_PLAYER_NATION:
4324 gtk_tree_model_get(model, &iter, 1, &id, -1);
4325 if (!(0 <= id && id < nation_count()) || !present) {
4326 return;
4327 }
4328 old_id = nation_index(pv->data.v_nation);
4329 pv->data.v_nation = nation_by_number(id);
4330 gtk_list_store_set(ev->store, &iter, 0, TRUE, -1);
4332 gtk_list_store_set(ev->store, &iter, 0, FALSE, -1);
4333 gtk_label_set_text(GTK_LABEL(ev->panel_label),
4334 nation_adjective_translation(pv->data.v_nation));
4335 pixbuf = get_flag(pv->data.v_nation);
4337 if (pixbuf) {
4339 }
4340 break;
4341
4342 case OPID_PLAYER_GOV:
4343 gtk_tree_model_get(model, &iter, 1, &id, -1);
4344 if (!(0 <= id && id < government_count()) || !present) {
4345 return;
4346 }
4347 if (pv->data.v_gov != NULL) {
4348 old_id = government_index(pv->data.v_gov);
4349 pv->data.v_gov = government_by_number(id);
4350 gtk_list_store_set(ev->store, &iter, 0, TRUE, -1);
4352 gtk_list_store_set(ev->store, &iter, 0, FALSE, -1);
4353 } else {
4354 pv->data.v_gov = government_by_number(id);
4355 gtk_list_store_set(ev->store, &iter, 0, TRUE, -1);
4356 }
4357
4358 gtk_label_set_text(GTK_LABEL(ev->panel_label),
4359 government_name_translation(pv->data.v_gov));
4362 if (pixbuf) {
4364 }
4365 break;
4366
4368 gtk_tree_model_get(model, &iter, 1, &id, -1);
4369 if (!(A_FIRST <= id && id < advance_count())) {
4370 return;
4371 }
4372 if (present) {
4373 BV_SET(pv->data.v_bv_inventions, id);
4374 } else {
4375 BV_CLR(pv->data.v_bv_inventions, id);
4376 }
4377 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4379 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4380 g_free(buf);
4381 break;
4382
4383 default:
4384 log_error("Unhandled widget toggled signal in "
4385 "extviewer_view_cell_toggled() for objprop id=%d "
4386 "name \"%s\".", propid, objprop_get_name(op));
4387 return;
4388 break;
4389 }
4390
4392}
4393
4394/************************************************************************/
4399{
4400 struct extviewer *ev;
4401 struct objprop *op;
4402 struct property_page *pp;
4404 struct propval value = {{0,}, VALTYPE_STRING, FALSE}, *pv;
4405 GtkTextIter start, end;
4406 char *text;
4407 gchar *buf;
4408
4409 ev = userdata;
4410 if (!ev) {
4411 return;
4412 }
4413
4417
4418 gtk_text_buffer_get_start_iter(textbuf, &start);
4419 gtk_text_buffer_get_end_iter(textbuf, &end);
4420 text = gtk_text_buffer_get_text(textbuf, &start, &end, FALSE);
4421 value.data.v_const_string = text;
4422 pv = &value;
4423
4424 switch (propid) {
4428 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4429 g_free(buf);
4430 break;
4431 default:
4432 log_error("Unhandled widget modified signal in "
4433 "extviewer_textbuf_changed() for objprop id=%d "
4434 "name \"%s\".", propid, objprop_get_name(op));
4435 return;
4436 break;
4437 }
4438
4440 g_free(text);
4441}
4442
4443/************************************************************************/
4447{
4448#define ADDPROP(ARG_id, ARG_name, ARG_tooltip, ARG_flags, ARG_valtype) do { \
4449 struct objprop *MY_op = objprop_new(ARG_id, ARG_name, ARG_tooltip, \
4450 ARG_flags, ARG_valtype, pp); \
4451 objprop_hash_insert(pp->objprop_table, MY_op->id, MY_op); \
4452} while (FALSE)
4453
4454 switch (property_page_get_objtype(pp)) {
4455 case OBJTYPE_TILE:
4456 ADDPROP(OPID_TILE_IMAGE, _("Image"), NULL,
4458 ADDPROP(OPID_TILE_TERRAIN, _("Terrain"), NULL,
4460 ADDPROP(OPID_TILE_RESOURCE, _("Resource"), NULL,
4462 ADDPROP(OPID_TILE_INDEX, _("Index"), NULL,
4464 ADDPROP(OPID_TILE_X, Q_("?coordinate:X"), NULL,
4466 ADDPROP(OPID_TILE_Y, Q_("?coordinate:Y"), NULL,
4468 /* TRANS: The coordinate X in native coordinates.
4469 * The freeciv coordinate system is described in doc/HACKING. */
4470 ADDPROP(OPID_TILE_NAT_X, _("NAT X"), NULL,
4472 /* TRANS: The coordinate Y in native coordinates.
4473 * The freeciv coordinate system is described in doc/HACKING. */
4474 ADDPROP(OPID_TILE_NAT_Y, _("NAT Y"), NULL,
4476 ADDPROP(OPID_TILE_CONTINENT, _("Continent"), NULL,
4478 ADDPROP(OPID_TILE_XY, Q_("?coordinates:X,Y"), NULL,
4480 ADDPROP(OPID_TILE_SPECIALS, _("Specials"), NULL,
4483 ADDPROP(OPID_TILE_ROADS, _("Roads"), NULL,
4486 ADDPROP(OPID_TILE_BASES, _("Bases"), NULL,
4489#ifdef FREECIV_DEBUG
4490 ADDPROP(OPID_TILE_ADDRESS, _("Address"), NULL,
4492#endif /* FREECIV_DEBUG */
4493#if 0
4494 /* Disabled entirely for now as server is not sending other
4495 * players' vision information anyway. */
4496 ADDPROP(OPID_TILE_VISION, _("Vision"), NULL,
4498#endif
4499 /* TRANS: Tile property "Label" label in editor */
4500 ADDPROP(OPID_TILE_LABEL, Q_("?property:Label"), NULL,
4502 return;
4503
4504 case OBJTYPE_STARTPOS:
4505 ADDPROP(OPID_STARTPOS_IMAGE, _("Image"), NULL,
4507 ADDPROP(OPID_STARTPOS_XY, Q_("?coordinates:X,Y"), NULL,
4509 ADDPROP(OPID_STARTPOS_EXCLUDE, _("Exclude Nations"), NULL,
4511 ADDPROP(OPID_STARTPOS_NATIONS, _("Nations"), NULL,
4514 return;
4515
4516 case OBJTYPE_UNIT:
4517 ADDPROP(OPID_UNIT_IMAGE, _("Image"), NULL,
4519#ifdef FREECIV_DEBUG
4520 ADDPROP(OPID_UNIT_ADDRESS, _("Address"), NULL,
4522#endif /* FREECIV_DEBUG */
4523 ADDPROP(OPID_UNIT_TYPE, _("Type"), NULL,
4525 ADDPROP(OPID_UNIT_ID, _("ID"), NULL,
4527 ADDPROP(OPID_UNIT_XY, Q_("?coordinates:X,Y"), NULL,
4529 ADDPROP(OPID_UNIT_MOVES_LEFT, _("Moves Left"), NULL,
4531 ADDPROP(OPID_UNIT_FUEL, _("Fuel"), NULL,
4533 ADDPROP(OPID_UNIT_MOVED, _("Moved"), NULL,
4535 ADDPROP(OPID_UNIT_DONE_MOVING, _("Done Moving"), NULL,
4537 /* TRANS: HP = Hit Points of a unit. */
4538 ADDPROP(OPID_UNIT_HP, _("HP"), NULL,
4540 ADDPROP(OPID_UNIT_VETERAN, _("Veteran"), NULL,
4542 ADDPROP(OPID_UNIT_STAY, _("Stay put"), NULL,
4544 return;
4545
4546 case OBJTYPE_CITY:
4547 ADDPROP(OPID_CITY_IMAGE, _("Image"), NULL,
4549 ADDPROP(OPID_CITY_NAME, _("Name"), NULL,
4551#ifdef FREECIV_DEBUG
4552 ADDPROP(OPID_CITY_ADDRESS, _("Address"), NULL,
4554#endif /* FREECIV_DEBUG */
4555 ADDPROP(OPID_CITY_ID, _("ID"), NULL,
4557 ADDPROP(OPID_CITY_XY, Q_("?coordinates:X,Y"), NULL,
4559 ADDPROP(OPID_CITY_SIZE, _("Size"), NULL,
4561 ADDPROP(OPID_CITY_HISTORY, _("History"), NULL,
4563 ADDPROP(OPID_CITY_BUILDINGS, _("Buildings"), NULL,
4566 ADDPROP(OPID_CITY_FOOD_STOCK, _("Food Stock"), NULL,
4568 ADDPROP(OPID_CITY_SHIELD_STOCK, _("Shield Stock"), NULL,
4570 return;
4571
4572 case OBJTYPE_PLAYER:
4573 ADDPROP(OPID_PLAYER_NAME, _("Name"), NULL,
4576#ifdef FREECIV_DEBUG
4577 ADDPROP(OPID_PLAYER_ADDRESS, _("Address"), NULL,
4579#endif /* FREECIV_DEBUG */
4580 ADDPROP(OPID_PLAYER_NATION, _("Nation"), NULL,
4583 ADDPROP(OPID_PLAYER_GOV, _("Government"), NULL,
4585 VALTYPE_GOV);
4586 ADDPROP(OPID_PLAYER_AGE, _("Age"), NULL,
4588 ADDPROP(OPID_PLAYER_INVENTIONS, _("Inventions"), NULL,
4593 ADDPROP(OPID_PLAYER_SELECT_WEIGHT, _("Select Weight"),
4594 _("How likely user is to get this player by autoselect. '-1' for default behavior."),
4596 VALTYPE_INT);
4597 ADDPROP(OPID_PLAYER_SCIENCE, _("Science"), NULL,
4599 ADDPROP(OPID_PLAYER_GOLD, _("Gold"), NULL,
4601 VALTYPE_INT);
4602 ADDPROP(OPID_PLAYER_INFRAPOINTS, _("Infrapoints"), NULL,
4604 VALTYPE_INT);
4605 return;
4606
4607 case OBJTYPE_GAME:
4608 ADDPROP(OPID_GAME_SCENARIO, _("Scenario"), NULL,
4610 VALTYPE_BOOL);
4612 _("Scenario Name"), NULL,
4616 _("Scenario Authors"), NULL,
4620 _("Scenario Description"), NULL,
4624 _("Save Random Number State"), NULL,
4627 _("Save Players"), NULL,
4630 _("Nation Start Positions"), NULL,
4633 _("Prevent New Cities"), NULL,
4636 _("Saltwater Flooding Lakes"), NULL,
4639 _("Lock to current Ruleset"), NULL,
4641 return;
4642
4643 case NUM_OBJTYPES:
4644 break;
4645 }
4646
4647 log_error("%s(): Unhandled page object type %s (nb %d).", __FUNCTION__,
4650#undef ADDPROP
4651}
4652
4653/************************************************************************/
4676
4677/************************************************************************/
4682 GtkTreeModel *model,
4685 gpointer data)
4686{
4687 struct property_page *pp;
4688 struct objbind *ob = NULL, *old_ob;
4690
4691 pp = data;
4692 if (!pp || !sel_path) {
4693 return TRUE;
4694 }
4695
4696 if (!gtk_tree_model_get_iter(model, &iter, sel_path)) {
4697 return TRUE;
4698 }
4699
4701 gtk_tree_model_get(model, &iter, 0, &ob, -1);
4702 if (currently_selected) {
4703 if (ob == old_ob) {
4704 GList *rows, *p;
4705 GtkTreePath *path;
4706 struct objbind *new_ob = NULL;
4707
4709 for (p = rows; p != NULL; p = p->next) {
4710 path = p->data;
4711 if (gtk_tree_model_get_iter(model, &iter, path)) {
4712 struct objbind *test_ob = NULL;
4713 gtk_tree_model_get(model, &iter, 0, &test_ob, -1);
4714 if (test_ob == ob) {
4715 continue;
4716 }
4717 new_ob = test_ob;
4718 break;
4719 }
4720 }
4723
4725 }
4726 } else {
4728 }
4729
4730 return TRUE;
4731}
4732
4733/************************************************************************/
4738{
4739 struct property_page *pp;
4740 const gchar *text;
4741 GtkWidget *w;
4743 struct property_filter *pf;
4744 bool matched;
4745
4746 pp = userdata;
4748 pf = property_filter_new(text);
4749
4753 continue;
4754 }
4757 if (objprop_has_widget(op) && w != nullptr) {
4759 }
4761 if (objprop_show_in_listview(op) && col != nullptr) {
4763 }
4765
4767}
4768
4769/************************************************************************/
4773static struct property_page *
4775 struct property_editor *pe)
4776{
4777 struct property_page *pp;
4778 GtkWidget *vgrid, *vgrid2, *hgrid, *hgrid2, *paned, *frame, *w;
4779 GtkWidget *scrollwin, *view, *label, *entry, *notebook;
4780 GtkWidget *button, *hsep;
4785 int num_columns = 0;
4787 int col_id = 1;
4788 const char *attr_type_str, *name, *tooltip;
4789 gchar *title;
4790 int grid_row = 0;
4791 int grid2_row = 0;
4792 int grid_col = 0;
4793 int grid2_col = 0;
4794
4795 if (!(objtype < NUM_OBJTYPES)) {
4796 return NULL;
4797 }
4798
4799 pp = fc_calloc(1, sizeof(struct property_page));
4800 pp->objtype = objtype;
4801 pp->pe_parent = pe;
4802
4804
4805 pp->objprop_table = objprop_hash_new();
4807
4808 pp->objbind_table = objbind_hash_new();
4809
4810 pp->tag_table = stored_tag_hash_new();
4811
4814 num_columns++;
4815 }
4817
4818 /* Column zero in the store holds an objbind
4819 * pointer and is never displayed. */
4820 num_columns++;
4823
4828 col_id++;
4829 }
4831
4834
4837 pp->widget = paned;
4838
4839 /* Left side object list view. */
4840
4841 vgrid = gtk_grid_new();
4850
4853 TRUE);
4858
4862 gtk_widget_add_css_class(GTK_WIDGET(view), "large-pixbufs");
4863
4866 continue;
4867 }
4868
4870 if (!attr_type_str) {
4871 continue;
4872 }
4874 if (col_id < 0) {
4875 continue;
4876 }
4878 if (!name) {
4879 continue;
4880 }
4882 if (!cell) {
4883 continue;
4884 }
4885
4888 NULL);
4889
4893 if (objprop_is_sortable(op)) {
4896 } else {
4898 }
4901
4903
4906 g_signal_connect(sel, "changed",
4910
4912 pp->object_view = view;
4913
4915 hgrid = gtk_grid_new();
4918
4919 button = gtk_button_new();
4920 gtk_button_set_icon_name(GTK_BUTTON(button), "list-add");
4921 gtk_button_set_label(GTK_BUTTON(button), _("Create"));
4924 _("Pressing this button will create a new object of the "
4925 "same type as the current property page and add it to "
4926 "the page. The specific type and count of the objects "
4927 "is taken from the editor tool state. So for example, "
4928 "the \"tool value\" of the unit tool and its \"count\" "
4929 "parameter affect unit creation."));
4930 g_signal_connect(button, "clicked",
4932 gtk_grid_attach(GTK_GRID(hgrid), button, grid_col++, 0, 1, 1);
4933
4934 button = gtk_button_new();
4935 gtk_button_set_icon_name(GTK_BUTTON(button), "list-remove");
4936 gtk_button_set_label(GTK_BUTTON(button), _("Destroy"));
4939 _("Pressing this button will send a request to the server "
4940 "to destroy (i.e. erase) the objects selected in the object "
4941 "list."));
4942 g_signal_connect(button, "clicked",
4944 gtk_grid_attach(GTK_GRID(hgrid), button, grid_col++, 0, 1, 1);
4945 }
4946
4947 /* Right side properties panel. */
4948
4949 hgrid = gtk_grid_new();
4950 grid_col = 0;
4953
4954 vgrid = gtk_grid_new();
4963
4964 /* Extended property viewer to the right of the properties panel.
4965 * This needs to be created before property widgets, since some
4966 * might try to append themselves to this notebook. */
4967
4968 vgrid2 = gtk_grid_new();
4975
4976 notebook = gtk_notebook_new();
4977 gtk_widget_set_vexpand(notebook, TRUE);
4978 gtk_widget_set_size_request(notebook, 256, -1);
4981 gtk_grid_attach(GTK_GRID(vgrid2), notebook, 0, grid2_row++, 1, 1);
4982 pp->extviewer_notebook = notebook;
4983
4986
4987 hgrid2 = gtk_grid_new();
4993
4994 button = gtk_button_new_with_mnemonic(_("_Close"));
4996 g_signal_connect_swapped(button, "clicked",
4997 G_CALLBACK(gtk_window_close), pe->widget);
4998 gtk_grid_attach(GTK_GRID(hgrid2), button, grid2_col++, 0, 1, 1);
4999
5000 /* Now create the properties panel. */
5001
5002 /* TRANS: %s is a type of object that can be edited, such as "Tile",
5003 * "Unit", "Start Position", etc. */
5004 title = g_strdup_printf(_("%s Properties"),
5006 frame = gtk_frame_new(title);
5007 g_free(title);
5008 gtk_widget_set_size_request(frame, 256, -1);
5009 gtk_grid_attach(GTK_GRID(vgrid), frame, 0, grid_row++, 1, 1);
5010
5013 FALSE);
5018
5019 vgrid2 = gtk_grid_new();
5020 grid2_row = 0;
5030
5032 if (!objprop_has_widget(op)) {
5033 continue;
5034 }
5036 if (!w) {
5037 continue;
5038 }
5039 gtk_grid_attach(GTK_GRID(vgrid2), w, 0, grid2_row++, 1, 1);
5041 if (NULL != tooltip) {
5043 }
5045
5046 hgrid2 = gtk_grid_new();
5047 grid2_col = 0;
5052
5053 label = gtk_label_new(_("Filter:"));
5054 gtk_grid_attach(GTK_GRID(hgrid2), label, grid2_col++, 0, 1, 1);
5055
5056 entry = gtk_entry_new();
5058 _("Enter a filter string to limit which properties are shown. "
5059 "The filter is one or more text patterns separated by | "
5060 "(\"or\") or & (\"and\"). The symbol & has higher precedence "
5061 "than |. A pattern may also be negated by prefixing it with !."));
5062 g_signal_connect(entry, "changed",
5065
5066 hgrid2 = gtk_grid_new();
5067 grid2_col = 0;
5070
5071 button = gtk_button_new_with_mnemonic(_("_Refresh"));
5074 _("Pressing this button will reset all modified properties of "
5075 "the selected objects to their current values (the values "
5076 "they have on the server)."));
5077 g_signal_connect(button, "clicked",
5079 gtk_grid_attach(GTK_GRID(hgrid2), button, grid2_col++, 0, 1, 1);
5080
5081 button = gtk_button_new_with_mnemonic(_("_Apply"));
5084 _("Pressing this button will send all modified properties of "
5085 "the objects selected in the object list to the server. "
5086 "Modified properties' names are shown in red in the properties "
5087 "panel."));
5088 g_signal_connect(button, "clicked",
5090 gtk_grid_attach(GTK_GRID(hgrid2), button, grid2_col++, 0, 1, 1);
5091
5092 return pp;
5093}
5094
5095/************************************************************************/
5098static const char *property_page_get_name(const struct property_page *pp)
5099{
5100 if (!pp) {
5101 return "";
5102 }
5104}
5105
5106/************************************************************************/
5109static enum editor_object_type
5111{
5112 if (!pp) {
5113 return -1;
5114 }
5115 return pp->objtype;
5116}
5117
5118/************************************************************************/
5126static GdkPixbuf *create_tile_pixbuf(const struct tile *ptile)
5127{
5129}
5130
5131/************************************************************************/
5142
5143/************************************************************************/
5155
5156/************************************************************************/
5164static GdkPixbuf *create_pixbuf_from_layers(const struct tile *ptile,
5165 const struct unit *punit,
5166 const struct city *pcity,
5167 enum layer_category category)
5168{
5170 int h, fh, fw, canvas_x, canvas_y;
5172 cairo_t *cr;
5173
5177
5179
5182 cairo_paint(cr);
5183 cairo_destroy(cr);
5184
5185 canvas_x = 0;
5186 canvas_y = 0;
5187
5188 canvas_y += (fh - h);
5189
5190 mapview_layer_iterate(layer) {
5191 if (tileset_layer_in_category(layer, category)) {
5192 put_one_element(&canvas, 1.0, layer,
5193 ptile, NULL, NULL, punit, pcity,
5195 }
5199
5200 return pixbuf;
5201}
5202
5203/************************************************************************/
5207{
5208 if (!pp) {
5209 return;
5210 }
5211
5212 gtk_list_store_clear(pp->object_store);
5213 objbind_hash_clear(pp->objbind_table);
5215}
5216
5217/************************************************************************/
5223{
5224 struct objbind *ob;
5226 int id;
5227
5228 if (!pp) {
5229 return;
5230 }
5231
5234 if (id < 0) {
5235 return;
5236 }
5237
5238 if (objbind_hash_lookup(pp->objbind_table, id, NULL)) {
5239 /* Object already exists. */
5240 return;
5241 }
5242
5244 if (!ob) {
5245 return;
5246 }
5247
5249
5250 objbind_hash_insert(pp->objbind_table, ob->object_id, ob);
5251}
5252
5253/************************************************************************/
5258 const struct tile *ptile)
5259{
5260
5261 if (!pp || !ptile) {
5262 return;
5263 }
5264
5265 switch (property_page_get_objtype(pp)) {
5266 case OBJTYPE_TILE:
5268 return;
5269
5270 case OBJTYPE_STARTPOS:
5271 {
5272 struct startpos *psp = map_startpos_get(ptile);
5273
5274 if (NULL != psp) {
5276 }
5277 }
5278 return;
5279
5280 case OBJTYPE_UNIT:
5281 unit_list_iterate(ptile->units, punit) {
5284 return;
5285
5286 case OBJTYPE_CITY:
5287 if (tile_city(ptile)) {
5289 }
5290 return;
5291
5292 case OBJTYPE_PLAYER:
5293 case OBJTYPE_GAME:
5294 return;
5295
5296 case NUM_OBJTYPES:
5297 break;
5298 }
5299
5300 log_error("%s(): Unhandled page object type %s (nb %d).", __FUNCTION__,
5303}
5304
5305/************************************************************************/
5312 struct objprop *op,
5313 struct objbind *ob,
5315{
5316 int col_id;
5317 struct propval *pv;
5318 enum value_types valtype;
5319 char buf[128], *p;
5321 GtkListStore *store;
5322 gchar *buf2;
5323
5324 if (!pp || !pp->object_store || !op || !ob) {
5325 return FALSE;
5326 }
5327
5329 return FALSE;
5330 }
5331
5333 if (col_id < 0) {
5334 return FALSE;
5335 }
5336
5338 if (!pv) {
5339 return FALSE;
5340 }
5341
5343 store = pp->object_store;
5344
5345 switch (valtype) {
5346 case VALTYPE_NONE:
5347 break;
5348 case VALTYPE_INT:
5349 gtk_list_store_set(store, iter, col_id, pv->data.v_int, -1);
5350 break;
5351 case VALTYPE_BOOL:
5352 /* Set as translated string, not as untranslated G_TYPE_BOOLEAN */
5354 break;
5355 case VALTYPE_STRING:
5356 if (fc_strlcpy(buf, pv->data.v_string, 28) >= 28) {
5357 sz_strlcat(buf, "...");
5358 }
5359 for (p = buf; *p; p++) {
5360 if (*p == '\n' || *p == '\t' || *p == '\r') {
5361 *p = ' ';
5362 }
5363 }
5364 gtk_list_store_set(store, iter, col_id, buf, -1);
5365 break;
5366 case VALTYPE_PIXBUF:
5367 gtk_list_store_set(store, iter, col_id, pv->data.v_pixbuf, -1);
5368 break;
5371 case VALTYPE_BV_SPECIAL:
5372 case VALTYPE_BV_ROADS:
5373 case VALTYPE_BV_BASES:
5376 gtk_list_store_set(store, iter, col_id, buf2, -1);
5377 g_free(buf2);
5378 break;
5379 case VALTYPE_NATION:
5380 pixbuf = get_flag(pv->data.v_nation);
5381 gtk_list_store_set(store, iter, col_id, pixbuf, -1);
5382 if (pixbuf) {
5384 }
5385 break;
5386 case VALTYPE_GOV:
5387 if (pv->data.v_gov != NULL) {
5389 } else {
5392 }
5393 gtk_list_store_set(store, iter, col_id, pixbuf, -1);
5394 if (pixbuf) {
5396 }
5397 break;
5399 break;
5400 }
5401
5403
5404 return TRUE;
5405}
5406
5407/************************************************************************/
5412{
5413 struct objbind *focused;
5414
5415 if (!pp || !pp->objbind_table) {
5416 return;
5417 }
5418
5419 if (pp->object_store) {
5422 GtkTreeModel *model;
5423 GtkTreePath *path;
5424
5425 model = GTK_TREE_MODEL(pp->object_store);
5426
5428 if (objbind_get_rowref(ob)) {
5429 continue;
5430 }
5431 gtk_list_store_append(pp->object_store, &iter);
5432 gtk_list_store_set(pp->object_store, &iter, 0, ob, -1);
5433 path = gtk_tree_model_get_path(model, &iter);
5434 rr = gtk_tree_row_reference_new(model, path);
5435 gtk_tree_path_free(path);
5437
5442
5443 if (gtk_tree_model_get_iter_first(model, &iter)) {
5445
5448 }
5449 }
5450
5455}
5456
5457/************************************************************************/
5462{
5463 if (!pp) {
5464 return NULL;
5465 }
5466 return pp->focused_objbind;
5467}
5468
5469/************************************************************************/
5474 struct objbind *ob)
5475{
5476 if (!pp) {
5477 return;
5478 }
5479 pp->focused_objbind = ob;
5480}
5481
5482/************************************************************************/
5487 int object_id)
5488{
5489 struct objbind *ob;
5490
5491 if (!pp || !pp->objbind_table) {
5492 return NULL;
5493 }
5494
5495 objbind_hash_lookup(pp->objbind_table, object_id, &ob);
5496 return ob;
5497}
5498
5499/************************************************************************/
5504 const struct tile_list *tiles)
5505{
5506 if (!pp || !tiles) {
5507 return;
5508 }
5509
5510 tile_list_iterate(tiles, ptile) {
5513
5515}
5516
5517/************************************************************************/
5521{
5522 if (!pp || !pp->objbind_table) {
5523 return 0;
5524 }
5525 return objbind_hash_size(pp->objbind_table);
5526}
5527
5528/************************************************************************/
5533 struct objprop *op,
5534 struct propval *pv)
5535{
5537 GtkTreeModel *model;
5538 GList *rows, *p;
5539 GtkTreePath *path;
5541 struct objbind *ob;
5542 bool changed = FALSE;
5543
5544 if (!pp || !op || !pp->object_view) {
5545 return;
5546 }
5547
5548 if (objprop_is_readonly(op)) {
5549 return;
5550 }
5551
5554
5555 for (p = rows; p != NULL; p = p->next) {
5556 path = p->data;
5557 if (gtk_tree_model_get_iter(model, &iter, path)) {
5558 gtk_tree_model_get(model, &iter, 0, &ob, -1);
5559 changed |= objbind_set_modified_value(ob, op, pv);
5560 }
5561 gtk_tree_path_free(path);
5562 }
5564
5565 if (changed) {
5568 }
5569}
5570
5571/************************************************************************/
5575{
5577 GtkTreeModel *model;
5578 GList *rows, *p;
5579 GtkTreePath *path;
5581 struct objbind *ob;
5582 union packetdata packet;
5583 struct connection *my_conn = &client.conn;
5584
5585 if (!pp || !pp->object_view) {
5586 return;
5587 }
5588
5591 return;
5592 }
5593
5594 packet = property_page_new_packet(pp);
5595 if (!packet.pointers.v_pointer1) {
5596 return;
5597 }
5598
5601 for (p = rows; p != NULL; p = p->next) {
5602 path = p->data;
5603 if (gtk_tree_model_get_iter(model, &iter, path)) {
5604 gtk_tree_model_get(model, &iter, 0, &ob, -1);
5608 if (objprop_is_readonly(op)) {
5609 continue;
5610 }
5614 }
5615 }
5616 gtk_tree_path_free(path);
5617 }
5620
5622}
5623
5624/************************************************************************/
5629{
5630 union packetdata packet;
5631
5632 packet.pointers.v_pointer2 = NULL;
5633
5634 if (!pp) {
5635 packet.pointers.v_pointer1 = NULL;
5636 return packet;
5637 }
5638
5639 switch (property_page_get_objtype(pp)) {
5640 case OBJTYPE_TILE:
5641 packet.tile = fc_calloc(1, sizeof(*packet.tile));
5642 break;
5643 case OBJTYPE_STARTPOS:
5644 packet.startpos = fc_calloc(1, sizeof(*packet.startpos));
5645 break;
5646 case OBJTYPE_UNIT:
5647 packet.unit = fc_calloc(1, sizeof(*packet.unit));
5648 break;
5649 case OBJTYPE_CITY:
5650 packet.city = fc_calloc(1, sizeof(*packet.city));
5651 break;
5652 case OBJTYPE_PLAYER:
5653 packet.player = fc_calloc(1, sizeof(*packet.player));
5654 break;
5655 case OBJTYPE_GAME:
5656 packet.game.game = fc_calloc(1, sizeof(*packet.game.game));
5657 packet.game.desc = fc_calloc(1, sizeof(*packet.game.desc));
5658 break;
5659 case NUM_OBJTYPES:
5660 break;
5661 }
5662
5663 return packet;
5664}
5665
5666/************************************************************************/
5670 union packetdata packet)
5671{
5672 struct connection *my_conn = &client.conn;
5673
5674 if (!pp || !packet.pointers.v_pointer1) {
5675 return;
5676 }
5677
5678 switch (property_page_get_objtype(pp)) {
5679 case OBJTYPE_TILE:
5681 return;
5682 case OBJTYPE_STARTPOS:
5684 return;
5685 case OBJTYPE_UNIT:
5687 return;
5688 case OBJTYPE_CITY:
5690 return;
5691 case OBJTYPE_PLAYER:
5693 return;
5694 case OBJTYPE_GAME:
5695 send_packet_edit_game(my_conn, packet.game.game);
5697 return;
5698 case NUM_OBJTYPES:
5699 break;
5700 }
5701
5702 log_error("%s(): Unhandled object type %s (nb %d).",
5705}
5706
5707/************************************************************************/
5711 union packetdata packet)
5712{
5713 if (!packet.pointers.v_pointer1) {
5714 return;
5715 }
5716
5717 free(packet.pointers.v_pointer1);
5718 packet.pointers.v_pointer1 = NULL;
5719
5720 if (packet.pointers.v_pointer2 != NULL) {
5721 free(packet.pointers.v_pointer2);
5722 packet.pointers.v_pointer2 = NULL;
5723 }
5724}
5725
5726/************************************************************************/
5731{
5733 GtkTreeModel *model;
5735 GtkTreePath *path;
5736 GList *rows, *p;
5737 struct objbind *ob;
5738
5739 if (!pp || !pp->object_view) {
5740 return;
5741 }
5742
5745 return;
5746 }
5747
5749 for (p = rows; p != NULL; p = p->next) {
5750 path = p->data;
5751 if (gtk_tree_model_get_iter(model, &iter, path)) {
5752 gtk_tree_model_get(model, &iter, 0, &ob, -1);
5757 }
5758 gtk_tree_path_free(path);
5759 }
5761
5766}
5767
5768/************************************************************************/
5772{
5774 GtkTreeModel *model;
5776 GtkTreePath *path;
5777 GList *rows, *p;
5778 struct objbind *ob;
5779 struct connection *my_conn = &client.conn;
5780
5781 if (!pp || !pp->object_view) {
5782 return;
5783 }
5784
5787 return;
5788 }
5789
5792 for (p = rows; p != NULL; p = p->next) {
5793 path = p->data;
5794 if (gtk_tree_model_get_iter(model, &iter, path)) {
5795 gtk_tree_model_get(model, &iter, 0, &ob, -1);
5797 }
5798 gtk_tree_path_free(path);
5799 }
5802}
5803
5804/************************************************************************/
5811 struct tile_list *hint_tiles)
5812{
5814 int apno, value, count, size;
5815 int tag;
5816 struct connection *my_conn = &client.conn;
5817 struct tile *ptile = NULL;
5818 struct player *pplayer;
5819
5820 if (!pp) {
5821 return;
5822 }
5823
5826 return;
5827 }
5828
5829 tag = get_next_unique_tag();
5830 count = 1;
5831
5832 switch (objtype) {
5833 case OBJTYPE_STARTPOS:
5834 if (hint_tiles) {
5836 if (NULL == map_startpos_get(atile)) {
5837 ptile = atile;
5838 break;
5839 }
5841 }
5842
5843 if (NULL == ptile) {
5844 ptile = get_center_tile_mapcanvas();
5845 }
5846
5847 if (NULL == ptile) {
5848 break;
5849 }
5850
5852 break;
5853
5854 case OBJTYPE_UNIT:
5855 if (hint_tiles) {
5858 ptile = atile;
5859 break;
5860 }
5862 }
5863
5864 if (!ptile) {
5865 struct unit *punit;
5869 ptile = unit_tile(punit);
5870 break;
5871 }
5873 }
5874
5875 if (!ptile) {
5876 ptile = get_center_tile_mapcanvas();
5877 }
5878
5879 if (!ptile) {
5880 break;
5881 }
5882
5887 value, count, tag);
5888 break;
5889
5890 case OBJTYPE_CITY:
5892 pplayer = player_by_number(apno);
5893 if (pplayer && hint_tiles) {
5895 if (!is_enemy_unit_tile(atile, pplayer)
5897 NULL, FALSE)) {
5898 ptile = atile;
5899 break;
5900 }
5902 }
5903
5904 if (!ptile) {
5905 ptile = get_center_tile_mapcanvas();
5906 }
5907
5908 if (!ptile) {
5909 break;
5910 }
5911
5914 size, tag);
5915 break;
5916
5917 case OBJTYPE_PLAYER:
5919 break;
5920
5921 case OBJTYPE_TILE:
5922 case OBJTYPE_GAME:
5923 case NUM_OBJTYPES:
5924 break;
5925 }
5926
5928}
5929
5930/************************************************************************/
5936 int object_id,
5937 bool removed)
5938{
5939 struct objbind *ob;
5941
5943 if (!ob) {
5944 return;
5945 }
5946
5949 GtkTreePath *path;
5951 GtkTreeModel *model;
5952
5953 model = GTK_TREE_MODEL(pp->object_store);
5955
5956 if (gtk_tree_model_get_iter(model, &iter, path)) {
5957 if (removed) {
5958 gtk_list_store_remove(pp->object_store, &iter);
5959 } else {
5963 }
5964 }
5965
5966 gtk_tree_path_free(path);
5967 }
5968
5969 if (removed) {
5970 objbind_hash_remove(pp->objbind_table, object_id);
5971 return;
5972 }
5973
5978 }
5979}
5980
5981/************************************************************************/
5988 int tag, int object_id)
5989{
5992
5993 if (!property_page_tag_is_known(pp, tag)) {
5994 return;
5995 }
5997
6000
6001 if (!object) {
6002 return;
6003 }
6004
6007}
6008
6009/************************************************************************/
6014 struct extviewer *ev)
6015{
6016 GtkWidget *w;
6017
6018 if (!pp || !ev) {
6019 return;
6020 }
6021
6023 if (!w) {
6024 return;
6025 }
6026 gtk_notebook_append_page(GTK_NOTEBOOK(pp->extviewer_notebook), w, NULL);
6027}
6028
6029/************************************************************************/
6034 struct extviewer *ev)
6035{
6036 GtkWidget *w;
6037 GtkNotebook *notebook;
6038 int page;
6039
6040 if (!pp || !ev) {
6041 return;
6042 }
6043
6045 if (!w) {
6046 return;
6047 }
6048
6049 notebook = GTK_NOTEBOOK(pp->extviewer_notebook);
6050 page = gtk_notebook_page_num(notebook, w);
6051 gtk_notebook_set_current_page(notebook, page);
6052}
6053
6054/************************************************************************/
6059 int tag, int count)
6060{
6061 if (!pp || !pp->tag_table) {
6062 return;
6063 }
6064
6065 if (stored_tag_hash_lookup(pp->tag_table, tag, NULL)) {
6066 log_error("Attempted to insert object creation tag %d "
6067 "twice into tag table for property page %p (%d %s).",
6070 return;
6071 }
6072
6073 stored_tag_hash_insert(pp->tag_table, tag, count);
6074}
6075
6076/************************************************************************/
6081 int tag)
6082{
6083 int count;
6084
6085 if (!pp || !pp->tag_table) {
6086 return;
6087 }
6088
6089 if (stored_tag_hash_lookup(pp->tag_table, tag, &count)) {
6090 if (0 >= --count) {
6091 stored_tag_hash_remove(pp->tag_table, tag);
6092 }
6093 }
6094}
6095
6096/************************************************************************/
6099static bool property_page_tag_is_known(struct property_page *pp, int tag)
6100{
6101 if (!pp || !pp->tag_table) {
6102 return FALSE;
6103 }
6104 return stored_tag_hash_lookup(pp->tag_table, tag, NULL);
6105}
6106
6107/************************************************************************/
6111{
6112 if (!pp || !pp->tag_table) {
6113 return;
6114 }
6115 stored_tag_hash_clear(pp->tag_table);
6116}
6117
6118/************************************************************************/
6127
6128/************************************************************************/
6138
6139/************************************************************************/
6144{
6145 struct property_page *pp = userdata, *tile_pp;
6146 struct tile_list *tiles = NULL;
6147 struct tile *ptile;
6148
6149 if (!pp) {
6150 return;
6151 }
6152
6154 tiles = tile_list_new();
6155
6157 ptile = objbind_get_object(ob);
6158 if (ptile) {
6159 tile_list_append(tiles, ptile);
6160 }
6162
6164 tile_list_destroy(tiles);
6165}
6166
6167/************************************************************************/
6176
6177/************************************************************************/
6183{
6184 struct property_page *pp;
6185 GtkWidget *label;
6186 const char *name;
6187
6188 if (!pe || !pe->notebook) {
6189 return FALSE;
6190 }
6191
6192 if (!(objtype < NUM_OBJTYPES)) {
6193 return FALSE;
6194 }
6195
6197 if (!pp) {
6198 return FALSE;
6199 }
6200
6202 label = gtk_label_new(name);
6204 pp->widget, label);
6205
6206 pe->property_pages[objtype] = pp;
6207
6208 return TRUE;
6209}
6210
6211/************************************************************************/
6214static struct property_page *
6217{
6218 if (!pe || !(objtype < NUM_OBJTYPES)) {
6219 return NULL;
6220 }
6221
6222 return pe->property_pages[objtype];
6223}
6224
6225/************************************************************************/
6229{
6230 struct property_editor *pe;
6231 GtkWidget *win, *notebook, *vgrid;
6233 int grid_row = 0;
6234
6235 pe = fc_calloc(1, sizeof(*pe));
6236
6237 /* The property editor dialog window. */
6238
6239 win = gtk_window_new();
6240 gtk_window_set_title(GTK_WINDOW(win), _("Property Editor"));
6250 pe->widget = win;
6251
6252 vgrid = gtk_grid_new();
6254
6255 /* Property pages. */
6256
6260 pe->notebook = notebook;
6261
6262 for (objtype = 0; objtype < NUM_OBJTYPES; objtype++) {
6264 }
6265
6266 return pe;
6267}
6268
6269/************************************************************************/
6279
6280/************************************************************************/
6284 const struct tile_list *tiles)
6285{
6286 struct property_page *pp;
6288 int i;
6289 const enum editor_object_type preferred[] = {
6294 };
6295
6296 if (!pe || !tiles) {
6297 return;
6298 }
6299
6300 for (objtype = 0; objtype < NUM_OBJTYPES; objtype++) {
6303 }
6304
6305 for (i = 0; i < ARRAY_SIZE(preferred) - 1; i++) {
6308 break;
6309 }
6310 }
6311 objtype = preferred[i];
6313}
6314
6315/************************************************************************/
6321{
6322 if (pe == nullptr || pe->widget == nullptr) {
6323 return;
6324 }
6325
6326 gtk_widget_set_visible(pe->widget, TRUE);
6327
6329 if (objtype < NUM_OBJTYPES) {
6331 }
6332}
6333
6334/************************************************************************/
6338{
6339 if (pe == nullptr || pe->widget == nullptr) {
6340 return;
6341 }
6342
6344}
6345
6346/************************************************************************/
6352 int object_id,
6353 bool remove)
6354{
6355 struct property_page *pp;
6356
6357 if (!pe) {
6358 return;
6359 }
6360
6361 if (!(objtype < NUM_OBJTYPES)) {
6362 return;
6363 }
6364
6367}
6368
6369/************************************************************************/
6373 int tag, int object_id)
6374{
6376 struct property_page *pp;
6377
6378 for (objtype = 0; objtype < NUM_OBJTYPES; objtype++) {
6380 continue;
6381 }
6383 property_page_object_created(pp, tag, object_id);
6384 }
6385}
6386
6387/************************************************************************/
6391{
6393 struct property_page *pp;
6394
6395 if (!pe) {
6396 return;
6397 }
6398
6399 for (objtype = 0; objtype < NUM_OBJTYPES; objtype++) {
6403 }
6404}
6405
6406/************************************************************************/
6412{
6413 struct property_page *pp;
6414
6415 if (!pe) {
6416 return;
6417 }
6418
6420 if (!pp) {
6421 return;
6422 }
6423
6425
6426 switch (objtype) {
6427 case OBJTYPE_PLAYER:
6428 players_iterate(pplayer) {
6429 property_page_add_objbind(pp, pplayer);
6431 break;
6432 case OBJTYPE_GAME:
6434 break;
6435 case OBJTYPE_TILE:
6436 case OBJTYPE_STARTPOS:
6437 case OBJTYPE_UNIT:
6438 case OBJTYPE_CITY:
6439 case NUM_OBJTYPES:
6440 break;
6441 }
6442
6445}
6446
6447/************************************************************************/
6458static struct property_filter *property_filter_new(const char *filter)
6459{
6460 struct property_filter *pf;
6461 struct pf_conjunction *pfc;
6462 struct pf_pattern *pfp;
6465 const char *pattern;
6466 int i, j;
6467
6468 pf = fc_calloc(1, sizeof(*pf));
6469
6470 if (!filter || filter[0] == '\0') {
6471 return pf;
6472 }
6473
6477
6478 for (i = 0; i < or_clause_count; i++) {
6479 if (or_clauses[i][0] == '\0') {
6480 continue;
6481 }
6482 pfc = &pf->disjunction[pf->count];
6483
6487
6488 for (j = 0; j < and_clause_count; j++) {
6489 if (and_clauses[j][0] == '\0') {
6490 continue;
6491 }
6492 pfp = &pfc->conjunction[pfc->count];
6493 pattern = and_clauses[j];
6494
6495 switch (pattern[0]) {
6496 case '!':
6497 pfp->negate = TRUE;
6498 pfp->text = fc_strdup(pattern + 1);
6499 break;
6500 default:
6501 pfp->text = fc_strdup(pattern);
6502 break;
6503 }
6504 pfc->count++;
6505 }
6507 pf->count++;
6508 }
6509
6511
6512 return pf;
6513}
6514
6515/************************************************************************/
6533 const struct objprop *op)
6534{
6535 struct pf_pattern *pfp;
6536 struct pf_conjunction *pfc;
6537 const char *name;
6538 bool match, or_result, and_result;
6539 int i, j;
6540
6541 if (!pf) {
6542 return TRUE;
6543 }
6544 if (!op) {
6545 return FALSE;
6546 }
6547
6549 if (!name) {
6550 return FALSE;
6551 }
6552
6553 if (pf->count < 1) {
6554 return TRUE;
6555 }
6556
6557 or_result = FALSE;
6558
6559 for (i = 0; i < pf->count; i++) {
6560 pfc = &pf->disjunction[i];
6561 and_result = TRUE;
6562 for (j = 0; j < pfc->count; j++) {
6563 pfp = &pfc->conjunction[j];
6564 match = (pfp->text[0] == '\0'
6565 || fc_strcasestr(name, pfp->text));
6566 if (pfp->negate) {
6567 match = !match;
6568 }
6569 and_result = and_result && match;
6570 if (!and_result) {
6571 break;
6572 }
6573 }
6575 if (or_result) {
6576 break;
6577 }
6578 }
6579
6580 return or_result;
6581}
6582
6583/************************************************************************/
6587{
6588 struct pf_pattern *pfp;
6589 struct pf_conjunction *pfc;
6590 int i, j;
6591
6592 if (!pf) {
6593 return;
6594 }
6595
6596 for (i = 0; i < pf->count; i++) {
6597 pfc = &pf->disjunction[i];
6598 for (j = 0; j < pfc->count; j++) {
6599 pfp = &pfc->conjunction[j];
6600 if (pfp->text != NULL) {
6601 free(pfp->text);
6602 pfp->text = NULL;
6603 }
6604 }
6605 pfc->count = 0;
6606 }
6607 pf->count = 0;
6608 free(pf);
6609}
6610
6611/************************************************************************/
6615{
6616 switch (vl) {
6617 case V_MAIN:
6618 /* TRANS: Vision layer name. Feel free to leave untranslated. */
6619 return _("Seen (Main)");
6620 case V_INVIS:
6621 /* TRANS: Vision layer name. Feel free to leave untranslated. */
6622 return _("Seen (Invis)");
6623 case V_SUBSURFACE:
6624 /* TRANS: Vision layer name. Feel free to leave untranslated. */
6625 return _("Seen (Subsurface)");
6626 case V_COUNT:
6627 break;
6628 }
6629
6630 log_error("%s(): Unrecognized vision layer %d.", __FUNCTION__, vl);
6631 return _("Unknown");
6632}
Base_type_id base_number(const struct base_type *pbase)
Definition base.c:96
Base_type_id base_count(void)
Definition base.c:114
bool dbv_isset(const struct dbv *pdbv, int bit)
Definition bitvector.c:120
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ARE_EQUAL(vec1, vec2)
Definition bitvector.h:121
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
#define BV_CLR(bv, bit)
Definition bitvector.h:94
struct canvas int int canvas_y
Definition canvas_g.h:43
struct canvas int canvas_x
Definition canvas_g.h:43
int city_granary_size(int city_size)
Definition city.c:2173
bool city_can_be_built_here(const struct civ_map *nmap, const struct tile *ptile, const struct unit *punit, bool hut_test)
Definition city.c:1528
#define city_tile(_pcity_)
Definition city.h:565
static citizens city_size_get(const struct city *pcity)
Definition city.h:570
#define city_owner(_pcity_)
Definition city.h:564
#define MAX_CITY_SIZE
Definition city.h:104
#define I_DESTROYED
Definition city.h:246
#define I_NEVER
Definition city.h:245
struct civclient client
bool client_nation_is_in_current_set(const struct nation_type *pnation)
Definition climisc.c:1509
char * incite_cost
Definition comments.c:77
void connection_do_buffer(struct connection *pc)
Definition connection.c:325
void connection_do_unbuffer(struct connection *pc)
Definition connection.c:337
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:74
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 int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:78
int objtype
Definition editgui_g.h:28
int int id
Definition editgui_g.h:28
int editor_tool_get_size(enum editor_tool_type ett)
Definition editor.c:1218
int editor_tool_get_value(enum editor_tool_type ett)
Definition editor.c:409
int editor_tool_get_count(enum editor_tool_type ett)
Definition editor.c:1252
struct unit * editor_unit_virtual_create(void)
Definition editor.c:1405
int editor_tool_get_applied_player(enum editor_tool_type ett)
Definition editor.c:1341
editor_object_type
Definition editor.h:25
@ OBJTYPE_PLAYER
Definition editor.h:30
@ OBJTYPE_UNIT
Definition editor.h:28
@ OBJTYPE_STARTPOS
Definition editor.h:27
@ OBJTYPE_GAME
Definition editor.h:31
@ NUM_OBJTYPES
Definition editor.h:33
@ OBJTYPE_CITY
Definition editor.h:29
@ OBJTYPE_TILE
Definition editor.h:26
@ ETT_UNIT
Definition editor.h:42
@ ETT_CITY
Definition editor.h:43
struct extra_type_list * extra_type_list_by_cause(enum extra_cause cause)
Definition extras.c:249
const char * extra_name_translation(const struct extra_type *pextra)
Definition extras.c:194
#define extra_index(_e_)
Definition extras.h:183
#define extra_base_get(_e_)
Definition extras.h:190
#define extra_road_get(_e_)
Definition extras.h:191
#define extra_type_by_cause_iterate_end
Definition extras.h:339
#define extra_type_by_cause_iterate(_cause, _extra)
Definition extras.h:333
void free_tokens(char **tokens, size_t ntokens)
Definition fc_cmdline.c:203
int get_tokens(const char *str, char **tokens, size_t num_tokens, const char *delimiterset)
Definition fc_cmdline.c:166
const struct functions * fc_funcs
#define EC_SPECIAL
Definition fc_types.h:809
#define Q_(String)
Definition fcintl.h:70
#define PL_(String1, String2, n)
Definition fcintl.h:71
#define _(String)
Definition fcintl.h:67
struct civ_game game
Definition game.c:62
struct world wld
Definition game.c:63
struct unit * game_unit_by_number(int id)
Definition game.c:116
struct city * game_city_by_number(int id)
Definition game.c:107
const char * government_name_translation(const struct government *pgovern)
Definition government.c:145
Government_type_id government_count(void)
Definition government.c:73
struct government * government_by_number(const Government_type_id gov)
Definition government.c:105
Government_type_id government_index(const struct government *pgovern)
Definition government.c:84
#define governments_iterate(NAME_pgov)
Definition government.h:127
#define governments_iterate_end
Definition government.h:130
#define FC_STATIC_CANVAS_INIT
Definition canvas.h:28
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:820
static void property_page_reset_objbinds(struct property_page *pp)
Definition editprop.c:5705
static void property_page_send_values(struct property_page *pp)
Definition editprop.c:5549
static void objprop_setup_widget(struct objprop *op)
Definition editprop.c:2954
static void property_page_store_creation_tag(struct property_page *pp, int tag, int count)
Definition editprop.c:6032
static gchar * propval_as_string(struct propval *pv)
Definition editprop.c:862
static struct property_page * objprop_get_property_page(const struct objprop *op)
Definition editprop.c:3466
static const char * objprop_get_name(const struct objprop *op)
Definition editprop.c:2834
const char * vision_layer_get_name(enum vision_layer)
Definition editprop.c:6586
static int objbind_get_object_id(struct objbind *ob)
Definition editprop.c:1382
static void objprop_set_extviewer(struct objprop *op, struct extviewer *ev)
Definition editprop.c:3443
static GtkWidget * extviewer_get_panel_widget(struct extviewer *ev)
Definition editprop.c:3798
static gpointer objtype_get_object_from_id(enum editor_object_type objtype, int id)
Definition editprop.c:725
void property_editor_handle_object_changed(struct property_editor *pe, enum editor_object_type objtype, int object_id, bool remove)
Definition editprop.c:6322
static struct propstate * propstate_new(struct objprop *op, struct propval *pv)
Definition editprop.c:1266
static const char * valtype_get_name(enum value_types valtype)
Definition editprop.c:779
static void propstate_destroy(struct propstate *ps)
Definition editprop.c:1298
static bool objbind_set_modified_value(struct objbind *ob, struct objprop *op, struct propval *pv)
Definition editprop.c:2130
static GtkCellRenderer * objprop_create_cell_renderer(const struct objprop *op)
Definition editprop.c:2858
static void extviewer_clear_widgets(struct extviewer *ev)
Definition editprop.c:4091
value_types
Definition editprop.c:197
@ VALTYPE_STRING
Definition editprop.c:201
@ VALTYPE_BV_SPECIAL
Definition editprop.c:205
@ VALTYPE_BV_BASES
Definition editprop.c:207
@ VALTYPE_INT
Definition editprop.c:199
@ VALTYPE_INVENTIONS_ARRAY
Definition editprop.c:204
@ VALTYPE_BV_ROADS
Definition editprop.c:206
@ VALTYPE_PIXBUF
Definition editprop.c:202
@ VALTYPE_TILE_VISION_DATA
Definition editprop.c:211
@ VALTYPE_NONE
Definition editprop.c:198
@ VALTYPE_NATION_HASH
Definition editprop.c:209
@ VALTYPE_BOOL
Definition editprop.c:200
@ VALTYPE_NATION
Definition editprop.c:208
@ VALTYPE_GOV
Definition editprop.c:210
@ VALTYPE_BUILT_ARRAY
Definition editprop.c:203
static void objprop_set_child_widget(struct objprop *op, const char *widget_name, GtkWidget *widget)
Definition editprop.c:3383
static bool property_editor_add_page(struct property_editor *pe, enum editor_object_type objtype)
Definition editprop.c:6155
static void propstate_clear_value(struct propstate *ps)
Definition editprop.c:1285
static void objbind_pack_modified_value(struct objbind *ob, struct objprop *op, union packetdata packet)
Definition editprop.c:2382
static struct objbind * property_page_get_focused_objbind(struct property_page *pp)
Definition editprop.c:5436
static bool objprop_has_widget(const struct objprop *op)
Definition editprop.c:2747
static int objtype_get_id_from_object(enum editor_object_type objtype, gpointer object)
Definition editprop.c:696
static enum editor_object_type objbind_get_objtype(const struct objbind *ob)
Definition editprop.c:2214
static struct extviewer * objprop_get_extviewer(struct objprop *op)
Definition editprop.c:3455
static void extviewer_refresh_widgets(struct extviewer *ev, struct propval *pv)
Definition editprop.c:3821
static enum editor_object_type property_page_get_objtype(const struct property_page *pp)
Definition editprop.c:5086
#define property_page_objbind_iterate_end
Definition editprop.c:641
static void property_page_show_extviewer(struct property_page *pp, struct extviewer *ev)
Definition editprop.c:6007
static gpointer objbind_get_object(struct objbind *ob)
Definition editprop.c:1366
static const char * property_page_get_name(const struct property_page *pp)
Definition editprop.c:5074
void property_editor_handle_object_created(struct property_editor *pe, int tag, int object_id)
Definition editprop.c:6344
static bool objbind_property_is_modified(struct objbind *ob, struct objprop *op)
Definition editprop.c:2085
static struct propval * propstate_get_value(struct propstate *ps)
Definition editprop.c:1328
static void property_page_clear_tags(struct property_page *pp)
Definition editprop.c:6084
static void property_page_object_created(struct property_page *pp, int tag, int object_id)
Definition editprop.c:5961
static bool property_page_tag_is_known(struct property_page *pp, int tag)
Definition editprop.c:6073
static void property_page_remove_creation_tag(struct property_page *pp, int tag)
Definition editprop.c:6054
static void property_page_load_tiles(struct property_page *pp, const struct tile_list *tiles)
Definition editprop.c:5478
static void property_page_create_objects(struct property_page *pp, struct tile_list *hint_tiles)
Definition editprop.c:5785
static void property_page_add_extviewer(struct property_page *pp, struct extviewer *ev)
Definition editprop.c:5987
static void property_page_refresh_button_clicked(GtkButton *button, gpointer userdata)
Definition editprop.c:6106
static void property_page_set_focused_objbind(struct property_page *pp, struct objbind *ob)
Definition editprop.c:5448
static void property_page_setup_objprops(struct property_page *pp)
Definition editprop.c:4436
static void objbind_set_rowref(struct objbind *ob, GtkTreeRowReference *rr)
Definition editprop.c:2654
object_property_flags
Definition editprop.c:384
@ OPF_IN_LISTVIEW
Definition editprop.c:387
@ OPF_EDITABLE
Definition editprop.c:386
@ OPF_HAS_WIDGET
Definition editprop.c:388
@ OPF_NO_FLAGS
Definition editprop.c:385
static void objbind_clear_modified_value(struct objbind *ob, struct objprop *op)
Definition editprop.c:2071
static struct propval * objbind_get_value_from_object(struct objbind *ob, struct objprop *op)
Definition editprop.c:1443
static void propval_free(struct propval *pv)
Definition editprop.c:1128
static struct property_filter * property_filter_new(const char *filter)
Definition editprop.c:6430
static bool property_page_set_store_value(struct property_page *pp, struct objprop *op, struct objbind *ob, GtkTreeIter *iter)
Definition editprop.c:5287
static const char * objtype_get_name(enum editor_object_type objtype)
Definition editprop.c:667
static void objbind_clear_all_modified_values(struct objbind *ob)
Definition editprop.c:2116
static bool property_filter_match(struct property_filter *pf, const struct objprop *op)
Definition editprop.c:6504
void property_editor_popup(struct property_editor *pe, enum editor_object_type objtype)
Definition editprop.c:6292
static void property_page_destroy_button_clicked(GtkButton *button, gpointer userdata)
Definition editprop.c:6144
static struct objbind * objbind_new(enum editor_object_type objtype, gpointer object)
Definition editprop.c:1340
static gboolean property_page_selection_func(GtkTreeSelection *sel, GtkTreeModel *model, GtkTreePath *path, gboolean currently_selected, gpointer data)
Definition editprop.c:4671
static int property_page_get_num_objbinds(const struct property_page *pp)
Definition editprop.c:5495
static bool objprop_show_in_listview(const struct objprop *op)
Definition editprop.c:2736
static GType objprop_get_gtype(const struct objprop *op)
Definition editprop.c:2692
static void objprop_set_treeview_column(struct objprop *op, GtkTreeViewColumn *col)
Definition editprop.c:2810
static void objbind_pack_current_values(struct objbind *ob, union packetdata packet)
Definition editprop.c:2239
static const char * objprop_get_attribute_type_string(const struct objprop *op)
Definition editprop.c:2761
static struct propval * propval_copy(struct propval *pv)
Definition editprop.c:1046
struct property_editor * editprop_get_property_editor(void)
Definition editprop.c:6245
void property_editor_reload(struct property_editor *pe, enum editor_object_type objtype)
Definition editprop.c:6382
static GdkPixbuf * create_unit_pixbuf(const struct unit *punit)
Definition editprop.c:5114
static void extviewer_view_cell_toggled(GtkCellRendererToggle *cell, gchar *path, gpointer userdata)
Definition editprop.c:4166
static struct property_editor * property_editor_new(void)
Definition editprop.c:6202
static void property_page_send_packet(struct property_page *pp, union packetdata packet)
Definition editprop.c:5644
static gchar * built_status_to_string(struct built_status *bs)
Definition editprop.c:981
static int objprop_get_id(const struct objprop *op)
Definition editprop.c:2677
object_property_ids
Definition editprop.c:305
@ OPID_STARTPOS_IMAGE
Definition editprop.c:325
@ OPID_TILE_Y
Definition editprop.c:308
@ OPID_TILE_BASES
Definition editprop.c:321
@ OPID_CITY_XY
Definition editprop.c:351
@ OPID_UNIT_ID
Definition editprop.c:335
@ OPID_CITY_BUILDINGS
Definition editprop.c:354
@ OPID_CITY_NAME
Definition editprop.c:346
@ OPID_TILE_NAT_Y
Definition editprop.c:310
@ OPID_CITY_SIZE
Definition editprop.c:352
@ OPID_UNIT_VETERAN
Definition editprop.c:342
@ OPID_CITY_IMAGE
Definition editprop.c:345
@ OPID_CITY_SHIELD_STOCK
Definition editprop.c:356
@ OPID_PLAYER_NAME
Definition editprop.c:358
@ OPID_PLAYER_AGE
Definition editprop.c:361
@ OPID_STARTPOS_NATIONS
Definition editprop.c:328
@ OPID_GAME_LAKE_FLOODING
Definition editprop.c:380
@ OPID_UNIT_IMAGE
Definition editprop.c:330
@ OPID_TILE_TERRAIN
Definition editprop.c:315
@ OPID_TILE_SPECIALS
Definition editprop.c:319
@ OPID_TILE_RESOURCE
Definition editprop.c:318
@ OPID_TILE_IMAGE
Definition editprop.c:306
@ OPID_TILE_VISION
Definition editprop.c:322
@ OPID_PLAYER_INVENTIONS
Definition editprop.c:365
@ OPID_GAME_SCENARIO_NAME
Definition editprop.c:373
@ OPID_PLAYER_SCIENCE
Definition editprop.c:368
@ OPID_TILE_CONTINENT
Definition editprop.c:311
@ OPID_CITY_HISTORY
Definition editprop.c:353
@ OPID_TILE_XY
Definition editprop.c:317
@ OPID_GAME_SCENARIO_AUTHORS
Definition editprop.c:374
@ OPID_PLAYER_SELECT_WEIGHT
Definition editprop.c:367
@ OPID_TILE_X
Definition editprop.c:307
@ OPID_TILE_NAT_X
Definition editprop.c:309
@ OPID_PLAYER_NATION
Definition editprop.c:359
@ OPID_GAME_PREVENT_CITIES
Definition editprop.c:379
@ OPID_STARTPOS_XY
Definition editprop.c:326
@ OPID_UNIT_MOVED
Definition editprop.c:339
@ OPID_TILE_LABEL
Definition editprop.c:323
@ OPID_CITY_FOOD_STOCK
Definition editprop.c:355
@ OPID_UNIT_DONE_MOVING
Definition editprop.c:340
@ OPID_UNIT_MOVES_LEFT
Definition editprop.c:337
@ OPID_GAME_SCENARIO_DESC
Definition editprop.c:375
@ OPID_GAME_STARTPOS_NATIONS
Definition editprop.c:378
@ OPID_UNIT_HP
Definition editprop.c:341
@ OPID_UNIT_FUEL
Definition editprop.c:338
@ OPID_PLAYER_SCENARIO_RESERVED
Definition editprop.c:366
@ OPID_TILE_ROADS
Definition editprop.c:320
@ OPID_PLAYER_GOLD
Definition editprop.c:369
@ OPID_CITY_ID
Definition editprop.c:350
@ OPID_GAME_SCENARIO_RANDSTATE
Definition editprop.c:376
@ OPID_PLAYER_INFRAPOINTS
Definition editprop.c:370
@ OPID_GAME_SCENARIO_PLAYERS
Definition editprop.c:377
@ OPID_UNIT_STAY
Definition editprop.c:343
@ OPID_PLAYER_GOV
Definition editprop.c:360
@ OPID_STARTPOS_EXCLUDE
Definition editprop.c:327
@ OPID_UNIT_TYPE
Definition editprop.c:334
@ OPID_GAME_SCENARIO
Definition editprop.c:372
@ OPID_GAME_RULESET_LOCKED
Definition editprop.c:381
@ OPID_UNIT_XY
Definition editprop.c:336
@ OPID_TILE_INDEX
Definition editprop.c:316
static enum value_types objprop_get_valtype(const struct objprop *op)
Definition editprop.c:2725
static int get_next_unique_tag(void)
Definition editprop.c:1035
static bool objprop_is_sortable(const struct objprop *op)
Definition editprop.c:2879
static void property_page_add_objbinds_from_tile(struct property_page *pp, const struct tile *ptile)
Definition editprop.c:5233
static const char * objprop_get_tooltip(const struct objprop *op)
Definition editprop.c:2845
static GtkTreeRowReference * objbind_get_rowref(struct objbind *ob)
Definition editprop.c:2666
static void property_filter_free(struct property_filter *pf)
Definition editprop.c:6558
static void objprop_widget_spin_button_changed(GtkSpinButton *spin, gpointer userdata)
Definition editprop.c:2920
#define PF_DISJUNCTION_SEPARATOR
Definition editprop.c:119
static GtkWidget * objprop_get_child_widget(struct objprop *op, const char *widget_name)
Definition editprop.c:3410
static void property_page_selection_changed(GtkTreeSelection *sel, gpointer userdata)
Definition editprop.c:4646
static bool objtype_is_conserved(enum editor_object_type objtype)
Definition editprop.c:756
static struct extviewer * extviewer_new(struct objprop *op)
Definition editprop.c:3502
static bool propval_equal(struct propval *pva, struct propval *pvb)
Definition editprop.c:1179
static void property_page_quick_find_entry_changed(GtkWidget *entry, gpointer userdata)
Definition editprop.c:4726
static void objprop_refresh_widget(struct objprop *op, struct objbind *ob)
Definition editprop.c:3132
#define PF_MAX_CLAUSES
Definition editprop.c:118
void property_editor_popdown(struct property_editor *pe)
Definition editprop.c:6310
static void objbind_destroy(struct objbind *ob)
Definition editprop.c:2195
static void property_page_add_objbind(struct property_page *pp, gpointer object_data)
Definition editprop.c:5197
static void objbind_request_destroy_object(struct objbind *ob)
Definition editprop.c:1395
static void property_page_create_button_clicked(GtkButton *button, gpointer userdata)
Definition editprop.c:6116
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:5140
static union packetdata property_page_new_packet(struct property_page *pp)
Definition editprop.c:5603
static void propstate_set_value(struct propstate *ps, struct propval *pv)
Definition editprop.c:1313
static int objprop_get_column_id(const struct objprop *op)
Definition editprop.c:2799
static GdkPixbuf * create_tile_pixbuf(const struct tile *ptile)
Definition editprop.c:5102
static struct objprop * extviewer_get_objprop(struct extviewer *ev)
Definition editprop.c:3786
static bool can_create_unit_at_tile(struct tile *ptile)
Definition editprop.c:1002
static struct objbind * property_page_get_objbind(struct property_page *pp, int object_id)
Definition editprop.c:5461
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:1884
static void property_page_free_packet(struct property_page *pp, union packetdata packet)
Definition editprop.c:5685
static GdkPixbuf * create_city_pixbuf(const struct city *pcity)
Definition editprop.c:5126
#define ADDPROP(ARG_id, ARG_name, ARG_tooltip, ARG_flags, ARG_valtype)
static void extviewer_panel_button_clicked(GtkButton *button, gpointer userdata)
Definition editprop.c:4146
static void property_page_destroy_objects(struct property_page *pp)
Definition editprop.c:5746
void property_editor_load_tiles(struct property_editor *pe, const struct tile_list *tiles)
Definition editprop.c:6256
static struct property_page * property_page_new(enum editor_object_type objtype, struct property_editor *parent)
Definition editprop.c:4768
#define property_page_objprop_iterate_end
Definition editprop.c:637
static void property_page_clear_objbinds(struct property_page *pp)
Definition editprop.c:5182
void property_editor_clear(struct property_editor *pe)
Definition editprop.c:6362
#define property_page_objprop_iterate(ARG_pp, NAME_op)
Definition editprop.c:635
static void objprop_set_column_id(struct objprop *op, int col_id)
Definition editprop.c:2786
static void objbind_bind_properties(struct objbind *ob, struct property_page *pp)
Definition editprop.c:2225
static void property_page_fill_widgets(struct property_page *pp)
Definition editprop.c:5387
static bool objbind_has_modified_properties(struct objbind *ob)
Definition editprop.c:2104
static void property_page_change_value(struct property_page *pp, struct objprop *op, struct propval *pv)
Definition editprop.c:5507
static void objprop_widget_toggle_button_changed(GtkToggleButton *button, gpointer userdata)
Definition editprop.c:2937
#define PF_CONJUNCTION_SEPARATOR
Definition editprop.c:120
static void property_page_apply_button_clicked(GtkButton *button, gpointer userdata)
Definition editprop.c:6095
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:3477
static GtkWidget * extviewer_get_view_widget(struct extviewer *ev)
Definition editprop.c:3810
static GtkWidget * objprop_get_widget(struct objprop *op)
Definition editprop.c:3368
static void propval_free_data(struct propval *pv)
Definition editprop.c:1142
static void extviewer_textbuf_changed(GtkTextBuffer *textbuf, gpointer userdata)
Definition editprop.c:4387
static struct property_editor * the_property_editor
Definition editprop.c:661
static void property_page_object_changed(struct property_page *pp, int object_id, bool remove)
Definition editprop.c:5909
static bool objprop_is_readonly(const struct objprop *op)
Definition editprop.c:2893
#define property_page_objbind_iterate(ARG_pp, NAME_ob)
Definition editprop.c:639
static GtkTreeViewColumn * objprop_get_treeview_column(const struct objprop *op)
Definition editprop.c:2823
static struct property_page * property_editor_get_page(struct property_editor *pe, enum editor_object_type objtype)
Definition editprop.c:6189
static struct propval * objbind_get_modified_value(struct objbind *ob, struct objprop *op)
Definition editprop.c:2176
GtkWidget * toplevel
Definition gui_main.c:126
void disable_gobject_callback(GObject *obj, GCallback cb)
Definition gui_stuff.c:1090
void enable_gobject_callback(GObject *obj, GCallback cb)
Definition gui_stuff.c:1106
GdkPixbuf * get_flag(const struct nation_type *nation)
Definition plrdlg.c:607
const char * tooltip
Definition repodlgs.c:1315
const char * title
Definition repodlgs.c:1314
GdkPixbuf * surface_get_pixbuf(cairo_surface_t *surf, int width, int height)
Definition sprite.c:418
GdkPixbuf * sprite_get_pixbuf(struct sprite *sprite)
Definition sprite.c:402
static void objprop_widget_text_changed(GtkEditable *text, gpointer userdata)
Definition editprop.c:2905
#define PF_MAX_CLAUSES
Definition editprop.c:118
bool is_special_improvement(const struct impr_type *pimprove)
Impr_type_id improvement_index(const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
const char * improvement_name_translation(const struct impr_type *pimprove)
bool is_small_wonder(const struct impr_type *pimprove)
#define improvement_iterate_end
#define improvement_iterate(_p)
#define B_LAST
Definition improvement.h:42
const char * name
Definition inputfile.c:127
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#define log_error(message,...)
Definition log.h:104
int dsend_packet_edit_city_create(struct connection *pc, int owner, int tile, int size, int tag)
int send_packet_edit_city(struct connection *pc, const struct packet_edit_city *packet)
int send_packet_edit_game(struct connection *pc, const struct packet_edit_game *packet)
int send_packet_edit_startpos_full(struct connection *pc, const struct packet_edit_startpos_full *packet)
int dsend_packet_edit_startpos(struct connection *pc, int id, bool removal, int tag)
int send_packet_edit_player(struct connection *pc, const struct packet_edit_player *packet)
int dsend_packet_edit_player_create(struct connection *pc, int tag)
int send_packet_edit_unit(struct connection *pc, const struct packet_edit_unit *packet)
int send_packet_edit_scenario_desc(struct connection *pc, const struct packet_edit_scenario_desc *packet)
int dsend_packet_edit_unit_remove_by_id(struct connection *pc, int id)
int dsend_packet_edit_unit_create(struct connection *pc, int owner, int tile, Unit_type_id type, int count, int tag)
int dsend_packet_edit_player_remove(struct connection *pc, int id)
int send_packet_edit_tile(struct connection *pc, const struct packet_edit_tile *packet)
int dsend_packet_edit_city_remove(struct connection *pc, int id)
struct startpos * map_startpos_get(const struct tile *ptile)
Definition map.c:2038
int startpos_number(const struct startpos *psp)
Definition map.c:1776
#define nat_x
#define nat_y
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1820
const struct nation_hash * startpos_raw_nations(const struct startpos *psp)
Definition map.c:1916
bool startpos_pack(const struct startpos *psp, struct packet_edit_startpos_full *packet)
Definition map.c:1854
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:471
bool startpos_is_excluding(const struct startpos *psp)
Definition map.c:1903
struct startpos * map_startpos_by_number(int id)
Definition map.c:1767
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition map.h:161
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition map.h:229
struct tile * get_center_tile_mapcanvas(void)
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)
#define fc_calloc(n, esz)
Definition mem.h:38
#define fc_strdup(str)
Definition mem.h:43
#define fc_malloc(sz)
Definition mem.h:34
bool can_unit_exist_at_tile(const struct civ_map *nmap, const struct unit *punit, const struct tile *ptile)
Definition movement.c:350
#define MAX_MOVE_FRAGS
Definition movement.h:29
Nation_type_id nation_count(void)
Definition nation.c:503
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:484
const char * nation_adjective_translation(const struct nation_type *pnation)
Definition nation.c:149
struct nation_type * nation_by_number(const Nation_type_id nation)
Definition nation.c:472
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:443
bool is_nation_playable(const struct nation_type *nation)
Definition nation.c:201
Nation_type_id nation_index(const struct nation_type *pnation)
Definition nation.c:495
enum barbarian_type nation_barbarian_type(const struct nation_type *nation)
Definition nation.c:212
#define nation_hash_iterate(nationhash, pnation)
Definition nation.h:93
#define nations_iterate_end
Definition nation.h:364
#define nations_iterate(NAME_pnation)
Definition nation.h:361
#define nation_hash_iterate_end
Definition nation.h:95
bool player_slot_is_used(const struct player_slot *pslot)
Definition player.c:441
struct player * player_by_number(const int player_id)
Definition player.c:837
int player_number(const struct player *pplayer)
Definition player.c:826
const char * player_name(const struct player *pplayer)
Definition player.c:885
int player_slot_index(const struct player_slot *pslot)
Definition player.c:423
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1979
int player_index(const struct player *pplayer)
Definition player.c:818
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1397
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:432
#define players_iterate_end
Definition player.h:552
#define players_iterate(_pplayer)
Definition player.h:547
#define player_slots_iterate(_pslot)
Definition player.h:538
#define player_slots_iterate_end
Definition player.h:542
struct research * research_get(const struct player *pplayer)
Definition research.c:130
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:622
Road_type_id road_count(void)
Definition road.c:50
Road_type_id road_number(const struct road_type *proad)
Definition road.c:32
#define ARRAY_SIZE(x)
Definition shared.h:85
int step
Definition specpq.h:92
size_t size
Definition specvec.h:72
cairo_surface_t * surface
Definition canvas.h:23
Definition city.h:318
struct packet_game_info info
Definition game.h:89
struct government * government_during_revolution
Definition game.h:94
struct connection conn
Definition client_main.h:96
GtkWidget * view_widget
Definition editprop.c:523
GtkWidget * panel_button
Definition editprop.c:520
GtkWidget * view_label
Definition editprop.c:524
GtkWidget * panel_image
Definition editprop.c:521
GtkTextBuffer * textbuf
Definition editprop.c:527
struct objprop * objprop
Definition editprop.c:515
GtkWidget * panel_label
Definition editprop.c:519
struct propval * pv_cached
Definition editprop.c:516
GtkListStore * store
Definition editprop.c:526
GtkWidget * panel_widget
Definition editprop.c:518
bool(* player_tile_vision_get)(const struct tile *ptile, const struct player *pplayer, enum vision_layer vision)
int object_id
Definition editprop.c:460
struct propstate_hash * propstate_table
Definition editprop.c:462
struct property_page * parent_property_page
Definition editprop.c:461
GtkTreeRowReference * rowref
Definition editprop.c:463
enum editor_object_type objtype
Definition editprop.c:459
const char * name
Definition editprop.c:393
const char * tooltip
Definition editprop.c:394
GtkWidget * widget
Definition editprop.c:399
struct property_page * parent_page
Definition editprop.c:401
enum object_property_flags flags
Definition editprop.c:395
struct extviewer * extviewer
Definition editprop.c:400
int id
Definition editprop.c:392
enum value_types valtype
Definition editprop.c:396
int column_id
Definition editprop.c:397
GtkTreeViewColumn * view_column
Definition editprop.c:398
char name[MAX_LEN_CITYNAME]
int built[B_LAST]
char scenario_name[256]
char scenario_authors[MAX_LEN_PACKET/3]
Nation_type_id nation
bool inventions[A_LAST+1]
char name[MAX_LEN_NAME]
Government_type_id government
bv_startpos_nations nations
char label[MAX_LEN_NAME]
struct pf_pattern conjunction[PF_MAX_CLAUSES]
Definition editprop.c:128
char * text
Definition editprop.c:124
bool negate
Definition editprop.c:123
int infra_points
Definition player.h:67
int autoselect_weight
Definition player.h:299
struct government * government
Definition player.h:258
int turns_alive
Definition player.h:266
struct player_economic economic
Definition player.h:284
char name[MAX_LEN_NAME]
Definition player.h:251
struct nation_type * nation
Definition player.h:260
GtkWidget * notebook
Definition editprop.c:649
struct property_page * property_pages[NUM_OBJTYPES]
Definition editprop.c:651
GtkWidget * widget
Definition editprop.c:648
struct pf_conjunction disjunction[PF_MAX_CLAUSES]
Definition editprop.c:133
GtkListStore * object_store
Definition editprop.c:553
struct property_editor * pe_parent
Definition editprop.c:557
GtkWidget * extviewer_notebook
Definition editprop.c:555
GtkWidget * widget
Definition editprop.c:552
struct objbind_hash * objbind_table
Definition editprop.c:560
GtkWidget * object_view
Definition editprop.c:554
struct objbind * focused_objbind
Definition editprop.c:563
struct stored_tag_hash * tag_table
Definition editprop.c:561
enum editor_object_type objtype
Definition editprop.c:550
struct objprop_hash * objprop_table
Definition editprop.c:559
struct propval * property_value
Definition editprop.c:256
int property_id
Definition editprop.c:255
union propval_data data
Definition editprop.c:244
enum value_types valtype
Definition editprop.c:245
bool must_free
Definition editprop.c:246
Definition map.c:40
bv_player tile_known
Definition editprop.c:114
bv_player tile_seen[V_COUNT]
Definition editprop.c:114
Definition tile.h:50
char * label
Definition tile.h:66
Continent_id continent
Definition tile.h:54
Definition unit.h:140
int moves_left
Definition unit.h:152
int id
Definition unit.h:147
bool moved
Definition unit.h:176
int hp
Definition unit.h:153
int fuel
Definition unit.h:155
bool stay
Definition unit.h:208
bool done_moving
Definition unit.h:184
int veteran
Definition unit.h:154
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:777
char * fc_strcasestr(const char *haystack, const char *needle)
Definition support.c:437
#define sz_strlcpy(dest, src)
Definition support.h:195
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define sz_strlcat(dest, src)
Definition support.h:196
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:305
Tech_type_id advance_index(const struct advance *padvance)
Definition tech.c:90
#define advance_index_iterate_end
Definition tech.h:246
static Tech_type_id advance_count(void)
Definition tech.h:167
#define A_FIRST
Definition tech.h:44
#define advance_iterate(_p)
Definition tech.h:273
#define advance_iterate_end
Definition tech.h:274
#define advance_index_iterate(_start, _index)
Definition tech.h:242
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:240
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_index(_pt_)
Definition tile.h:89
#define tile_resource(_tile)
Definition tile.h:103
#define tile_list_iterate(tile_list, ptile)
Definition tile.h:74
#define tile_terrain(_tile)
Definition tile.h:115
#define TILE_XY(ptile)
Definition tile.h:43
#define tile_list_iterate_end
Definition tile.h:76
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:125
#define tile_has_extra(ptile, pextra)
Definition tile.h:152
struct sprite * get_government_sprite(const struct tileset *t, const struct government *gov)
Definition tilespec.c:7043
int tileset_small_sprite_width(const struct tileset *t)
Definition tilespec.c:927
int tileset_full_tile_height(const struct tileset *t)
Definition tilespec.c:815
bool tileset_layer_in_category(enum mapview_layer layer, enum layer_category cat)
Definition tilespec.c:7591
int tileset_small_sprite_height(const struct tileset *t)
Definition tilespec.c:963
int tileset_tile_height(const struct tileset *t)
Definition tilespec.c:791
int tileset_full_tile_width(const struct tileset *t)
Definition tilespec.c:802
int tileset_tile_width(const struct tileset *t)
Definition tilespec.c:779
#define mapview_layer_iterate(layer)
Definition tilespec.h:178
#define mapview_layer_iterate_end
Definition tilespec.h:186
layer_category
Definition tilespec.h:192
@ LAYER_CATEGORY_TILE
Definition tilespec.h:194
@ LAYER_CATEGORY_CITY
Definition tilespec.h:193
@ LAYER_CATEGORY_UNIT
Definition tilespec.h:195
gpointer v_pointer2
Definition editprop.c:99
struct packet_edit_tile * tile
Definition editprop.c:101
gpointer v_pointer1
Definition editprop.c:98
struct packet_edit_unit * unit
Definition editprop.c:104
struct packet_edit_player * player
Definition editprop.c:105
struct packetdata::@152 pointers
struct packet_edit_city * city
Definition editprop.c:103
struct packet_edit_game * game
Definition editprop.c:107
struct packet_edit_startpos_full * startpos
Definition editprop.c:102
struct government * v_gov
Definition editprop.c:238
bv_techs v_bv_inventions
Definition editprop.c:239
bv_max_extras v_bv_special
Definition editprop.c:233
struct tile_vision_data * v_tile_vision
Definition editprop.c:240
char * v_string
Definition editprop.c:229
struct built_status * v_built
Definition editprop.c:232
bv_max_extras v_bv_roads
Definition editprop.c:234
gpointer v_pointer
Definition editprop.c:226
struct nation_type * v_nation
Definition editprop.c:236
struct nation_hash * v_nation_hash
Definition editprop.c:237
bv_max_extras v_bv_bases
Definition editprop.c:235
GdkPixbuf * v_pixbuf
Definition editprop.c:231
const char * v_const_string
Definition editprop.c:230
#define unit_tile(_pu)
Definition unit.h:407
static bool is_enemy_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:430
#define unit_owner(_pu)
Definition unit.h:406
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer, bool everyone_non_allied)
Definition unit.h:443
#define unit_list_iterate(unitlist, punit)
Definition unitlist.h:31
#define unit_list_iterate_end
Definition unitlist.h:33
const struct unit_type * unit_type_get(const struct unit *punit)
Definition unittype.c:126
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2657
bool unit_has_type_flag(const struct unit *punit, enum unit_type_flag_id flag)
Definition unittype.c:215
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1586
#define utype_fuel(ptype)
Definition unittype.h:847
#define vision_layer_iterate(v)
Definition vision.h:76
#define vision_layer_iterate_end
Definition vision.h:79