Freeciv-3.2
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)
1023 && (pcity == NULL
1024 || pplayers_allied(city_owner(pcity),
1025 unit_owner(vunit))));
1026 free(vunit);
1027
1028 return ret;
1029}
1030
1031/************************************************************************/
1034static int get_next_unique_tag(void)
1035{
1036 static int tag_series = 0;
1037
1038 tag_series++;
1039 return tag_series;
1040}
1041
1042/************************************************************************/
1045static struct propval *propval_copy(struct propval *pv)
1046{
1047 struct propval *pv_copy;
1048 size_t size;
1049
1050 if (!pv) {
1051 return NULL;
1052 }
1053
1054 pv_copy = fc_calloc(1, sizeof(*pv));
1055 pv_copy->valtype = pv->valtype;
1056
1057 switch (pv->valtype) {
1058 case VALTYPE_NONE:
1059 return pv_copy;
1060 case VALTYPE_INT:
1061 pv_copy->data.v_int = pv->data.v_int;
1062 return pv_copy;
1063 case VALTYPE_BOOL:
1064 pv_copy->data.v_bool = pv->data.v_bool;
1065 return pv_copy;
1066 case VALTYPE_STRING:
1067 pv_copy->data.v_string = fc_strdup(pv->data.v_string);
1068 pv_copy->must_free = TRUE;
1069 return pv_copy;
1070 case VALTYPE_PIXBUF:
1071 g_object_ref(pv->data.v_pixbuf);
1072 pv_copy->data.v_pixbuf = pv->data.v_pixbuf;
1073 pv_copy->must_free = TRUE;
1074 return pv_copy;
1076 size = B_LAST * sizeof(struct built_status);
1077 pv_copy->data.v_pointer = fc_malloc(size);
1078 memcpy(pv_copy->data.v_pointer, pv->data.v_pointer, size);
1079 pv_copy->must_free = TRUE;
1080 return pv_copy;
1081 case VALTYPE_BV_SPECIAL:
1082 pv_copy->data.v_bv_special = pv->data.v_bv_special;
1083 return pv_copy;
1084 case VALTYPE_BV_ROADS:
1085 pv_copy->data.v_bv_roads = pv->data.v_bv_roads;
1086 return pv_copy;
1087 case VALTYPE_BV_BASES:
1088 pv_copy->data.v_bv_bases = pv->data.v_bv_bases;
1089 return pv_copy;
1090 case VALTYPE_NATION:
1091 pv_copy->data.v_nation = pv->data.v_nation;
1092 return pv_copy;
1093 case VALTYPE_GOV:
1094 pv_copy->data.v_gov = pv->data.v_gov;
1095 return pv_copy;
1097 pv_copy->data.v_nation_hash
1098 = nation_hash_copy(pv->data.v_nation_hash);
1099 pv_copy->must_free = TRUE;
1100 return pv_copy;
1102 pv_copy->data.v_bv_inventions = pv->data.v_bv_inventions;
1103 return pv_copy;
1105 size = sizeof(struct tile_vision_data);
1106 pv_copy->data.v_tile_vision = fc_malloc(size);
1107 pv_copy->data.v_tile_vision->tile_known
1108 = pv->data.v_tile_vision->tile_known;
1110 pv_copy->data.v_tile_vision->tile_seen[v]
1111 = pv->data.v_tile_vision->tile_seen[v];
1113 pv_copy->must_free = TRUE;
1114 return pv_copy;
1115 }
1116
1117 log_error("%s(): Unhandled value type %d for property value %p.",
1118 __FUNCTION__, pv->valtype, pv);
1119 pv_copy->data = pv->data;
1120 return pv_copy;
1121}
1122
1123/************************************************************************/
1127static void propval_free(struct propval *pv)
1128{
1129 if (!pv) {
1130 return;
1131 }
1132
1134 free(pv);
1135}
1136
1137/************************************************************************/
1141static void propval_free_data(struct propval *pv)
1142{
1143 if (!pv || !pv->must_free) {
1144 return;
1145 }
1146
1147 switch (pv->valtype) {
1148 case VALTYPE_NONE:
1149 case VALTYPE_INT:
1150 case VALTYPE_BOOL:
1151 case VALTYPE_BV_SPECIAL:
1152 case VALTYPE_BV_ROADS:
1153 case VALTYPE_BV_BASES:
1154 case VALTYPE_NATION:
1155 case VALTYPE_GOV:
1156 return;
1157 case VALTYPE_PIXBUF:
1158 g_object_unref(pv->data.v_pixbuf);
1159 return;
1160 case VALTYPE_STRING:
1164 free(pv->data.v_pointer);
1165 return;
1167 nation_hash_destroy(pv->data.v_nation_hash);
1168 return;
1169 }
1170
1171 log_error("%s(): Unhandled request to free data %p (type %s).",
1172 __FUNCTION__, pv->data.v_pointer, valtype_get_name(pv->valtype));
1173}
1174
1175/************************************************************************/
1178static bool propval_equal(struct propval *pva,
1179 struct propval *pvb)
1180{
1181 if (!pva || !pvb) {
1182 return pva == pvb;
1183 }
1184
1185 if (pva->valtype != pvb->valtype) {
1186 return FALSE;
1187 }
1188
1189 switch (pva->valtype) {
1190 case VALTYPE_NONE:
1191 return TRUE;
1192 case VALTYPE_INT:
1193 return pva->data.v_int == pvb->data.v_int;
1194 case VALTYPE_BOOL:
1195 return pva->data.v_bool == pvb->data.v_bool;
1196 case VALTYPE_STRING:
1197 if (pva->data.v_const_string != NULL
1198 && pvb->data.v_const_string != NULL) {
1199 return !strcmp(pva->data.v_const_string,
1200 pvb->data.v_const_string);
1201 }
1202 return pva->data.v_const_string == pvb->data.v_const_string;
1203 case VALTYPE_PIXBUF:
1204 return pva->data.v_pixbuf == pvb->data.v_pixbuf;
1206 if (pva->data.v_pointer == pvb->data.v_pointer) {
1207 return TRUE;
1208 } else if (!pva->data.v_pointer || !pvb->data.v_pointer) {
1209 return FALSE;
1210 }
1211
1212 improvement_iterate(pimprove) {
1213 int id, vatb, vbtb;
1214 id = improvement_index(pimprove);
1215 vatb = pva->data.v_built[id].turn;
1216 vbtb = pvb->data.v_built[id].turn;
1217 if (vatb < 0 && vbtb < 0) {
1218 continue;
1219 }
1220 if (vatb != vbtb) {
1221 return FALSE;
1222 }
1224 return TRUE;
1226 return BV_ARE_EQUAL(pva->data.v_bv_inventions, pvb->data.v_bv_inventions);
1227 case VALTYPE_BV_SPECIAL:
1228 return BV_ARE_EQUAL(pva->data.v_bv_special, pvb->data.v_bv_special);
1229 case VALTYPE_BV_ROADS:
1230 return BV_ARE_EQUAL(pva->data.v_bv_roads, pvb->data.v_bv_roads);
1231 case VALTYPE_BV_BASES:
1232 return BV_ARE_EQUAL(pva->data.v_bv_bases, pvb->data.v_bv_bases);
1233 case VALTYPE_NATION:
1234 return pva->data.v_nation == pvb->data.v_nation;
1236 return nation_hashes_are_equal(pva->data.v_nation_hash,
1237 pvb->data.v_nation_hash);
1238 case VALTYPE_GOV:
1239 return pva->data.v_gov == pvb->data.v_gov;
1241 if (!BV_ARE_EQUAL(pva->data.v_tile_vision->tile_known,
1242 pvb->data.v_tile_vision->tile_known)) {
1243 return FALSE;
1244 }
1246 if (!BV_ARE_EQUAL(pva->data.v_tile_vision->tile_seen[v],
1247 pvb->data.v_tile_vision->tile_seen[v])) {
1248 return FALSE;
1249 }
1251 return TRUE;
1252 }
1253
1254 log_error("%s(): Unhandled value type %d for property values %p and %p.",
1255 __FUNCTION__, pva->valtype, pva, pvb);
1256 return pva->data.v_pointer == pvb->data.v_pointer;
1257}
1258
1259/************************************************************************/
1265static struct propstate *propstate_new(struct objprop *op,
1266 struct propval *pv)
1267{
1268 struct propstate *ps;
1269
1270 if (!op) {
1271 return NULL;
1272 }
1273
1274 ps = fc_calloc(1, sizeof(*ps));
1275 ps->property_id = objprop_get_id(op);
1276 ps->property_value = pv;
1277
1278 return ps;
1279}
1280
1281/************************************************************************/
1285{
1286 if (!ps) {
1287 return;
1288 }
1289
1290 propval_free(ps->property_value);
1291 ps->property_value = NULL;
1292}
1293
1294/************************************************************************/
1297static void propstate_destroy(struct propstate *ps)
1298{
1299 if (!ps) {
1300 return;
1301 }
1303 free(ps);
1304}
1305
1306/************************************************************************/
1313 struct propval *pv)
1314{
1315 if (!ps) {
1316 return;
1317 }
1319 ps->property_value = pv;
1320}
1321
1322/************************************************************************/
1328{
1329 if (!ps) {
1330 return NULL;
1331 }
1332 return ps->property_value;
1333}
1334
1335/************************************************************************/
1340 gpointer object)
1341{
1342 struct objbind *ob;
1343 int id;
1344
1345 if (object == NULL) {
1346 return NULL;
1347 }
1348
1349 id = objtype_get_id_from_object(objtype, object);
1350 if (id < 0) {
1351 return NULL;
1352 }
1353
1354 ob = fc_calloc(1, sizeof(*ob));
1355 ob->object_id = id;
1356 ob->objtype = objtype;
1357 ob->propstate_table = propstate_hash_new();
1358
1359 return ob;
1360}
1361
1362/************************************************************************/
1366{
1367 int id;
1368
1369 if (!ob) {
1370 return NULL;
1371 }
1372
1374
1375 return objtype_get_object_from_id(ob->objtype, id);
1376}
1377
1378/************************************************************************/
1382{
1383 if (NULL == ob) {
1384 return -1;
1385 }
1386 return ob->object_id;
1387}
1388
1389/************************************************************************/
1395{
1396 struct connection *my_conn = &client.conn;
1398 int id;
1399
1400 if (!ob) {
1401 return;
1402 }
1403
1406 return;
1407 }
1408
1410
1411 switch (objtype) {
1412 case OBJTYPE_STARTPOS:
1414 return;
1415 case OBJTYPE_UNIT:
1417 return;
1418 case OBJTYPE_CITY:
1420 return;
1421 case OBJTYPE_PLAYER:
1423 return;
1424 case OBJTYPE_TILE:
1425 case OBJTYPE_GAME:
1426 case NUM_OBJTYPES:
1427 break;
1428 }
1429
1430 log_error("%s(): Unhandled request to destroy object %p (ID %d) of type "
1431 "%d (%s).", __FUNCTION__, objbind_get_object(ob), id, objtype,
1433}
1434
1435/************************************************************************/
1443 struct objprop *op)
1444{
1447 struct propval *pv;
1448
1449 if (!ob || !op) {
1450 return NULL;
1451 }
1452
1455
1456 pv = fc_calloc(1, sizeof(*pv));
1457 pv->valtype = objprop_get_valtype(op);
1458
1459 switch (objtype) {
1460 case OBJTYPE_TILE:
1461 {
1462 const struct tile *ptile = objbind_get_object(ob);
1463 int tile_x, tile_y, nat_x, nat_y;
1464
1465 if (NULL == ptile) {
1466 goto FAILED;
1467 }
1468
1471
1472 switch (propid) {
1473 case OPID_TILE_IMAGE:
1474 pv->data.v_pixbuf = create_tile_pixbuf(ptile);
1475 pv->must_free = TRUE;
1476 break;
1477#ifdef FREECIV_DEBUG
1478 case OPID_TILE_ADDRESS:
1479 pv->data.v_string = g_strdup_printf("%p", ptile);
1480 pv->must_free = TRUE;
1481 break;
1482#endif /* FREECIV_DEBUG */
1483 case OPID_TILE_TERRAIN:
1484 {
1485 const struct terrain *pterrain = tile_terrain(ptile);
1486
1487 if (NULL != pterrain) {
1488 pv->data.v_const_string = terrain_name_translation(pterrain);
1489 } else {
1490 pv->data.v_const_string = "";
1491 }
1492 }
1493 break;
1494 case OPID_TILE_RESOURCE:
1495 {
1496 const struct extra_type *presource = tile_resource(ptile);
1497
1498 if (NULL != presource) {
1499 pv->data.v_const_string = extra_name_translation(presource);
1500 } else {
1501 pv->data.v_const_string = "";
1502 }
1503 }
1504 break;
1505 case OPID_TILE_XY:
1506 pv->data.v_string = g_strdup_printf("(%d, %d)", tile_x, tile_y);
1507 pv->must_free = TRUE;
1508 break;
1509 case OPID_TILE_INDEX:
1510 pv->data.v_int = tile_index(ptile);
1511 break;
1512 case OPID_TILE_X:
1513 pv->data.v_int = tile_x;
1514 break;
1515 case OPID_TILE_Y:
1516 pv->data.v_int = tile_y;
1517 break;
1518 case OPID_TILE_NAT_X:
1519 pv->data.v_int = nat_x;
1520 break;
1521 case OPID_TILE_NAT_Y:
1522 pv->data.v_int = nat_y;
1523 break;
1525 pv->data.v_int = ptile->continent;
1526 break;
1527 case OPID_TILE_SPECIALS:
1528 BV_CLR_ALL(pv->data.v_bv_special);
1530 if (tile_has_extra(ptile, pextra)) {
1531 BV_SET(pv->data.v_bv_special, pextra->data.special_idx);
1532 }
1534 break;
1535 case OPID_TILE_ROADS:
1536 BV_CLR_ALL(pv->data.v_bv_roads);
1538 if (tile_has_extra(ptile, pextra)) {
1539 BV_SET(pv->data.v_bv_roads, road_number(extra_road_get(pextra)));
1540 }
1542 break;
1543 case OPID_TILE_BASES:
1544 BV_CLR_ALL(pv->data.v_bv_bases);
1546 if (tile_has_extra(ptile, pextra)) {
1547 BV_SET(pv->data.v_bv_bases, base_number(extra_base_get(pextra)));
1548 }
1550 break;
1551 case OPID_TILE_VISION:
1552 pv->data.v_tile_vision = fc_malloc(sizeof(struct tile_vision_data));
1553
1554 /* The server saves the known tiles and the player vision in special
1555 * bitvectors with the number of tiles as index. Here we want the
1556 * information for one tile. Thus, the data is transformed to
1557 * bitvectors with the number of player slots as index. */
1558 BV_CLR_ALL(pv->data.v_tile_vision->tile_known);
1559 players_iterate(pplayer) {
1560 if (dbv_isset(&pplayer->tile_known, tile_index(ptile))) {
1561 BV_SET(pv->data.v_tile_vision->tile_known,
1562 player_index(pplayer));
1563 }
1565
1567 BV_CLR_ALL(pv->data.v_tile_vision->tile_seen[v]);
1568 players_iterate(pplayer) {
1569 if (fc_funcs->player_tile_vision_get(ptile, pplayer, v)) {
1570 BV_SET(pv->data.v_tile_vision->tile_seen[v],
1571 player_index(pplayer));
1572 }
1575 pv->must_free = TRUE;
1576 break;
1577 case OPID_TILE_LABEL:
1578 if (ptile->label != NULL) {
1579 pv->data.v_const_string = ptile->label;
1580 } else {
1581 pv->data.v_const_string = "";
1582 }
1583 break;
1584 default:
1585 log_error("%s(): Unhandled request for value of property %d "
1586 "(%s) from object of type \"%s\".", __FUNCTION__,
1588 goto FAILED;
1589 }
1590 }
1591 return pv;
1592
1593 case OBJTYPE_STARTPOS:
1594 {
1595 const struct startpos *psp = objbind_get_object(ob);
1596 const struct tile *ptile;
1597
1598 if (NULL == psp) {
1599 goto FAILED;
1600 }
1601
1602 switch (propid) {
1604 ptile = startpos_tile(psp);
1605 pv->data.v_pixbuf = create_tile_pixbuf(ptile);
1606 pv->must_free = TRUE;
1607 break;
1608 case OPID_STARTPOS_XY:
1609 ptile = startpos_tile(psp);
1610 pv->data.v_string = g_strdup_printf("(%d, %d)", TILE_XY(ptile));
1611 pv->must_free = TRUE;
1612 break;
1614 pv->data.v_bool = startpos_is_excluding(psp);
1615 break;
1617 pv->data.v_nation_hash = nation_hash_copy(startpos_raw_nations(psp));
1618 pv->must_free = TRUE;
1619 break;
1620 default:
1621 log_error("%s(): Unhandled request for value of property %d "
1622 "(%s) from object of type \"%s\".", __FUNCTION__,
1624 goto FAILED;
1625 }
1626 }
1627 return pv;
1628
1629 case OBJTYPE_UNIT:
1630 {
1631 struct unit *punit = objbind_get_object(ob);
1632
1633 if (NULL == punit) {
1634 goto FAILED;
1635 }
1636
1637 switch (propid) {
1638 case OPID_UNIT_IMAGE:
1639 pv->data.v_pixbuf = create_unit_pixbuf(punit);
1640 pv->must_free = TRUE;
1641 break;
1642#ifdef FREECIV_DEBUG
1643 case OPID_UNIT_ADDRESS:
1644 pv->data.v_string = g_strdup_printf("%p", punit);
1645 pv->must_free = TRUE;
1646 break;
1647#endif /* FREECIV_DEBUG */
1648 case OPID_UNIT_XY:
1649 {
1650 const struct tile *ptile = unit_tile(punit);
1651
1652 pv->data.v_string = g_strdup_printf("(%d, %d)", TILE_XY(ptile));
1653 pv->must_free = TRUE;
1654 }
1655 break;
1656 case OPID_UNIT_ID:
1657 pv->data.v_int = punit->id;
1658 break;
1659 case OPID_UNIT_TYPE:
1660 {
1661 const struct unit_type *putype = unit_type_get(punit);
1662
1663 pv->data.v_const_string = utype_name_translation(putype);
1664 }
1665 break;
1667 pv->data.v_int = punit->moves_left;
1668 break;
1669 case OPID_UNIT_FUEL:
1670 pv->data.v_int = punit->fuel;
1671 break;
1672 case OPID_UNIT_MOVED:
1673 pv->data.v_bool = punit->moved;
1674 break;
1676 pv->data.v_bool = punit->done_moving;
1677 break;
1678 case OPID_UNIT_HP:
1679 pv->data.v_int = punit->hp;
1680 break;
1681 case OPID_UNIT_VETERAN:
1682 pv->data.v_int = punit->veteran;
1683 break;
1684 case OPID_UNIT_STAY:
1685 pv->data.v_bool = punit->stay;
1686 break;
1687 default:
1688 log_error("%s(): Unhandled request for value of property %d "
1689 "(%s) from object of type \"%s\".", __FUNCTION__,
1691 goto FAILED;
1692 }
1693 }
1694 return pv;
1695
1696 case OBJTYPE_CITY:
1697 {
1698 const struct city *pcity = objbind_get_object(ob);
1699
1700 if (NULL == pcity) {
1701 goto FAILED;
1702 }
1703
1704 switch (propid) {
1705 case OPID_CITY_IMAGE:
1706 pv->data.v_pixbuf = create_city_pixbuf(pcity);
1707 pv->must_free = TRUE;
1708 break;
1709#ifdef FREECIV_DEBUG
1710 case OPID_CITY_ADDRESS:
1711 pv->data.v_string = g_strdup_printf("%p", pcity);
1712 pv->must_free = TRUE;
1713 break;
1714#endif /* FREECIV_DEBUG */
1715 case OPID_CITY_XY:
1716 {
1717 const struct tile *ptile = city_tile(pcity);
1718
1719 pv->data.v_string = g_strdup_printf("(%d, %d)", TILE_XY(ptile));
1720 pv->must_free = TRUE;
1721 }
1722 break;
1723 case OPID_CITY_ID:
1724 pv->data.v_int = pcity->id;
1725 break;
1726 case OPID_CITY_NAME:
1727 pv->data.v_const_string = pcity->name;
1728 break;
1729 case OPID_CITY_SIZE:
1730 pv->data.v_int = city_size_get(pcity);
1731 break;
1732 case OPID_CITY_HISTORY:
1733 pv->data.v_int = pcity->history;
1734 break;
1736 pv->data.v_built = fc_malloc(sizeof(pcity->built));
1737 memcpy(pv->data.v_built, pcity->built, sizeof(pcity->built));
1738 pv->must_free = TRUE;
1739 break;
1741 pv->data.v_int = pcity->food_stock;
1742 break;
1744 pv->data.v_int = pcity->shield_stock;
1745 break;
1746 default:
1747 log_error("%s(): Unhandled request for value of property %d "
1748 "(%s) from object of type \"%s\".", __FUNCTION__,
1750 goto FAILED;
1751 }
1752 }
1753 return pv;
1754
1755 case OBJTYPE_PLAYER:
1756 {
1757 const struct player *pplayer = objbind_get_object(ob);
1758 const struct research *presearch;
1759
1760 if (NULL == pplayer) {
1761 goto FAILED;
1762 }
1763
1764 switch (propid) {
1765 case OPID_PLAYER_NAME:
1766 pv->data.v_const_string = pplayer->name;
1767 break;
1768 case OPID_PLAYER_NATION:
1769 pv->data.v_nation = nation_of_player(pplayer);
1770 break;
1771 case OPID_PLAYER_GOV:
1772 pv->data.v_gov = pplayer->government;
1773 break;
1774 case OPID_PLAYER_AGE:
1775 pv->data.v_int = pplayer->turns_alive;
1776 break;
1777#ifdef FREECIV_DEBUG
1779 pv->data.v_string = g_strdup_printf("%p", pplayer);
1780 pv->must_free = TRUE;
1781 break;
1782#endif /* FREECIV_DEBUG */
1784 presearch = research_get(pplayer);
1785 BV_CLR_ALL(pv->data.v_bv_inventions);
1788 BV_SET(pv->data.v_bv_inventions, tech);
1789 }
1791 break;
1793 pv->data.v_bool = player_has_flag(pplayer, PLRF_SCENARIO_RESERVED);
1794 break;
1796 pv->data.v_int = pplayer->autoselect_weight;
1797 break;
1799 presearch = research_get(pplayer);
1800 pv->data.v_int = presearch->bulbs_researched;
1801 break;
1802 case OPID_PLAYER_GOLD:
1803 pv->data.v_int = pplayer->economic.gold;
1804 break;
1806 pv->data.v_int = pplayer->economic.infra_points;
1807 break;
1808 default:
1809 log_error("%s(): Unhandled request for value of property %d "
1810 "(%s) from object of type \"%s\".", __FUNCTION__,
1812 goto FAILED;
1813 }
1814 }
1815 return pv;
1816
1817 case OBJTYPE_GAME:
1818 {
1819 const struct civ_game *pgame = objbind_get_object(ob);
1820
1821 if (NULL == pgame) {
1822 goto FAILED;
1823 }
1824
1825 switch (propid) {
1826 case OPID_GAME_SCENARIO:
1827 pv->data.v_bool = pgame->scenario.is_scenario;
1828 break;
1830 pv->data.v_const_string = pgame->scenario.name;
1831 break;
1833 pv->data.v_const_string = pgame->scenario.authors;
1834 break;
1836 pv->data.v_const_string = pgame->scenario_desc.description;
1837 break;
1839 pv->data.v_bool = pgame->scenario.save_random;
1840 break;
1842 pv->data.v_bool = pgame->scenario.players;
1843 break;
1845 pv->data.v_bool = pgame->scenario.startpos_nations;
1846 break;
1848 pv->data.v_bool = pgame->scenario.prevent_new_cities;
1849 break;
1851 pv->data.v_bool = pgame->scenario.lake_flooding;
1852 break;
1854 pv->data.v_bool = pgame->scenario.ruleset_locked;
1855 break;
1856 default:
1857 log_error("%s(): Unhandled request for value of property %d "
1858 "(%s) from object of type \"%s\".", __FUNCTION__,
1860 goto FAILED;
1861 }
1862 }
1863 return pv;
1864
1865 case NUM_OBJTYPES:
1866 break;
1867 }
1868
1869 log_error("%s(): Unhandled request for object type \"%s\" (nb %d).",
1871
1872FAILED:
1873 if (NULL != pv) {
1874 free(pv);
1875 }
1876 return NULL;
1877}
1878
1879/************************************************************************/
1884 struct objprop *op,
1885 double *pmin,
1886 double *pmax,
1887 double *pstep,
1888 double *pbig_step)
1889{
1892 double dummy;
1893
1894 /* Fill the values with something. */
1895 if (NULL != pmin) {
1896 *pmin = 0;
1897 } else {
1898 pmin = &dummy;
1899 }
1900 if (NULL != pmax) {
1901 *pmax = 1;
1902 } else {
1903 pmax = &dummy;
1904 }
1905 if (NULL != pstep) {
1906 *pstep = 1;
1907 } else {
1908 pstep = &dummy;
1909 }
1910 if (NULL != pbig_step) {
1911 *pbig_step = 1;
1912 } else {
1913 pbig_step = &dummy;
1914 }
1915
1916 if (!ob || !op) {
1917 return FALSE;
1918 }
1919
1922
1923 switch (objtype) {
1924 case OBJTYPE_TILE:
1925 case OBJTYPE_STARTPOS:
1926 log_error("%s(): Unhandled request for value range of property %d (%s) "
1927 "from object of type \"%s\".", __FUNCTION__,
1929 return FALSE;
1930
1931 case OBJTYPE_UNIT:
1932 {
1933 const struct unit *punit = objbind_get_object(ob);
1934 const struct unit_type *putype;
1935
1936 if (NULL == punit) {
1937 return FALSE;
1938 }
1939
1941
1942 switch (propid) {
1944 *pmin = 0;
1946 *pstep = 1;
1947 *pbig_step = 5;
1948 return TRUE;
1949 case OPID_UNIT_FUEL:
1950 *pmin = 0;
1952 *pstep = 1;
1953 *pbig_step = 5;
1954 return TRUE;
1955 case OPID_UNIT_HP:
1956 *pmin = 1;
1957 *pmax = putype->hp;
1958 *pstep = 1;
1959 *pbig_step = 10;
1960 return TRUE;
1961 case OPID_UNIT_VETERAN:
1962 *pmin = 0;
1964 *pstep = 1;
1965 *pbig_step = 3;
1966 return TRUE;
1967 default:
1968 break;
1969 }
1970 }
1971 log_error("%s(): Unhandled request for value range of property %d (%s) "
1972 "from object of type \"%s\".", __FUNCTION__,
1974 return FALSE;
1975
1976 case OBJTYPE_CITY:
1977 {
1978 const struct city *pcity = objbind_get_object(ob);
1979
1980 if (NULL == pcity) {
1981 return FALSE;
1982 }
1983
1984 switch (propid) {
1985 case OPID_CITY_SIZE:
1986 *pmin = 1;
1988 *pstep = 1;
1989 *pbig_step = 5;
1990 return TRUE;
1991 case OPID_CITY_HISTORY:
1992 *pmin = 0;
1993 *pmax = USHRT_MAX;
1994 *pstep = 1;
1995 *pbig_step = 10;
1996 return TRUE;
1998 *pmin = 0;
2000 *pstep = 1;
2001 *pbig_step = 5;
2002 return TRUE;
2004 *pmin = 0;
2005 *pmax = USHRT_MAX; /* Limited to uint16 by city info packet. */
2006 *pstep = 1;
2007 *pbig_step = 10;
2008 return TRUE;
2009 default:
2010 break;
2011 }
2012 }
2013 log_error("%s(): Unhandled request for value range of property %d (%s) "
2014 "from object of type \"%s\".", __FUNCTION__,
2016 return FALSE;
2017
2018 case OBJTYPE_PLAYER:
2019 switch (propid) {
2021 *pmin = 0;
2022 *pmax = 1000000; /* Arbitrary. */
2023 *pstep = 1;
2024 *pbig_step = 100;
2025 return TRUE;
2026 case OPID_PLAYER_GOLD:
2027 *pmin = 0;
2028 *pmax = 1000000; /* Arbitrary. */
2029 *pstep = 1;
2030 *pbig_step = 100;
2031 return TRUE;
2033 *pmin = 0;
2034 *pmax = 1000000; /* Arbitrary. */
2035 *pstep = 1;
2036 *pbig_step = 100;
2037 return TRUE;
2039 *pmin = -1;
2040 *pmax = 10000; /* Keep it under SINT16 */
2041 *pstep = 1;
2042 *pbig_step = 10;
2043 return TRUE;
2044 default:
2045 break;
2046 }
2047 log_error("%s(): Unhandled request for value range of property %d (%s) "
2048 "from object of type \"%s\".", __FUNCTION__,
2050 return FALSE;
2051
2052 case OBJTYPE_GAME:
2053 log_error("%s(): Unhandled request for value range of property %d (%s) "
2054 "from object of type \"%s\".", __FUNCTION__,
2056 return FALSE;
2057
2058 case NUM_OBJTYPES:
2059 break;
2060 }
2061
2062 log_error("%s(): Unhandled request for object type \"%s\" (nb %d).",
2064 return FALSE;
2065}
2066
2067/************************************************************************/
2071 struct objprop *op)
2072{
2073 if (!ob || !op || !ob->propstate_table) {
2074 return;
2075 }
2076
2077 propstate_hash_remove(ob->propstate_table, objprop_get_id(op));
2078}
2079
2080/************************************************************************/
2085 struct objprop *op)
2086{
2087 if (!ob || !op) {
2088 return FALSE;
2089 }
2090
2091 if (objprop_is_readonly(op)) {
2092 return FALSE;
2093 }
2094
2095 return propstate_hash_lookup(ob->propstate_table,
2097}
2098
2099/************************************************************************/
2104{
2105 if (!ob) {
2106 return FALSE;
2107 }
2108
2109 return (0 < propstate_hash_size(ob->propstate_table));
2110}
2111
2112/************************************************************************/
2116{
2117 if (!ob) {
2118 return;
2119 }
2120 propstate_hash_clear(ob->propstate_table);
2121}
2122
2123/************************************************************************/
2130 struct objprop *op,
2131 struct propval *pv)
2132{
2133 struct propstate *ps;
2134 bool equal;
2135 struct propval *pv_old, *pv_copy;
2137
2138 if (!ob || !op) {
2139 return FALSE;
2140 }
2141
2143
2145 if (!pv_old) {
2146 return FALSE;
2147 }
2148
2151
2152 if (equal) {
2154 return FALSE;
2155 }
2156
2158
2159 if (propstate_hash_lookup(ob->propstate_table, propid, &ps)) {
2161 } else {
2163 propstate_hash_insert(ob->propstate_table, propid, ps);
2164 }
2165
2166 return TRUE;
2167}
2168
2169/************************************************************************/
2176 struct objprop *op)
2177{
2178 struct propstate *ps;
2179
2180 if (!ob || !op) {
2181 return NULL;
2182 }
2183
2184 if (propstate_hash_lookup(ob->propstate_table, objprop_get_id(op), &ps)) {
2185 return propstate_get_value(ps);
2186 } else {
2187 return NULL;
2188 }
2189}
2190
2191/************************************************************************/
2194static void objbind_destroy(struct objbind *ob)
2195{
2196 if (!ob) {
2197 return;
2198 }
2199 if (ob->propstate_table) {
2200 propstate_hash_destroy(ob->propstate_table);
2201 ob->propstate_table = NULL;
2202 }
2203 if (ob->rowref) {
2205 ob->rowref = NULL;
2206 }
2207 free(ob);
2208}
2209
2210/************************************************************************/
2214{
2215 if (!ob) {
2216 return NUM_OBJTYPES;
2217 }
2218 return ob->objtype;
2219}
2220
2221/************************************************************************/
2225 struct property_page *pp)
2226{
2227 if (!ob) {
2228 return;
2229 }
2230 ob->parent_property_page = pp;
2231}
2232
2233/************************************************************************/
2239 union packetdata pd)
2240{
2242
2243 if (!ob || !pd.pointers.v_pointer1) {
2244 return;
2245 }
2246
2248
2249 switch (objtype) {
2250 case OBJTYPE_TILE:
2251 {
2252 struct packet_edit_tile *packet = pd.tile;
2253 const struct tile *ptile = objbind_get_object(ob);
2254
2255 if (NULL == ptile) {
2256 return;
2257 }
2258
2259 packet->tile = tile_index(ptile);
2260 packet->extras = *tile_extras(ptile);
2261 /* TODO: Set more packet fields. */
2262 }
2263 return;
2264
2265 case OBJTYPE_STARTPOS:
2266 {
2267 struct packet_edit_startpos_full *packet = pd.startpos;
2268 const struct startpos *psp = objbind_get_object(ob);
2269
2270 if (NULL != psp) {
2271 startpos_pack(psp, packet);
2272 }
2273 }
2274 return;
2275
2276 case OBJTYPE_UNIT:
2277 {
2278 struct packet_edit_unit *packet = pd.unit;
2279 const struct unit *punit = objbind_get_object(ob);
2280
2281 if (NULL == punit) {
2282 return;
2283 }
2284
2285 packet->id = punit->id;
2286 packet->moves_left = punit->moves_left;
2287 packet->fuel = punit->fuel;
2288 packet->moved = punit->moved;
2289 packet->done_moving = punit->done_moving;
2290 packet->hp = punit->hp;
2291 packet->veteran = punit->veteran;
2292 packet->stay = punit->stay;
2293 /* TODO: Set more packet fields. */
2294 }
2295 return;
2296
2297 case OBJTYPE_CITY:
2298 {
2299 struct packet_edit_city *packet = pd.city;
2300 const struct city *pcity = objbind_get_object(ob);
2301 int i;
2302
2303 if (NULL == pcity) {
2304 return;
2305 }
2306
2307 packet->id = pcity->id;
2308 sz_strlcpy(packet->name, pcity->name);
2309 packet->size = city_size_get(pcity);
2310 packet->history = pcity->history;
2311 for (i = 0; i < B_LAST; i++) {
2312 packet->built[i] = pcity->built[i].turn;
2313 }
2314 packet->food_stock = pcity->food_stock;
2315 packet->shield_stock = pcity->shield_stock;
2316 /* TODO: Set more packet fields. */
2317 }
2318 return;
2319
2320 case OBJTYPE_PLAYER:
2321 {
2322 struct packet_edit_player *packet = pd.player;
2323 const struct player *pplayer = objbind_get_object(ob);
2324 const struct nation_type *pnation;
2325 const struct research *presearch;
2326
2327 if (NULL == pplayer) {
2328 return;
2329 }
2330
2331 packet->id = player_number(pplayer);
2332 sz_strlcpy(packet->name, pplayer->name);
2333 pnation = nation_of_player(pplayer);
2334 packet->nation = nation_index(pnation);
2335 presearch = research_get(pplayer);
2337 packet->inventions[tech]
2340 packet->autoselect_weight = pplayer->autoselect_weight;
2341 packet->gold = pplayer->economic.gold;
2342 packet->infrapoints = pplayer->economic.infra_points;
2343 packet->government = government_index(pplayer->government);
2345 /* TODO: Set more packet fields. */
2346 }
2347 return;
2348
2349 case OBJTYPE_GAME:
2350 {
2351 struct packet_edit_game *packet = pd.game.game;
2352 const struct civ_game *pgame = objbind_get_object(ob);
2353
2354 if (NULL == pgame) {
2355 return;
2356 }
2357
2358 packet->scenario = pgame->scenario.is_scenario;
2359 sz_strlcpy(packet->scenario_name, pgame->scenario.name);
2360 sz_strlcpy(packet->scenario_authors, pgame->scenario.authors);
2361 sz_strlcpy(pd.game.desc->scenario_desc, pgame->scenario_desc.description);
2362 packet->scenario_random = pgame->scenario.save_random;
2363 packet->scenario_players = pgame->scenario.players;
2364 packet->startpos_nations = pgame->scenario.startpos_nations;
2365 packet->prevent_new_cities = pgame->scenario.prevent_new_cities;
2366 packet->lake_flooding = pgame->scenario.lake_flooding;
2367 }
2368 return;
2369
2370 case NUM_OBJTYPES:
2371 break;
2372 }
2373
2374 log_error("%s(): Unhandled object type %s (nb %d).", __FUNCTION__,
2376}
2377
2378/************************************************************************/
2382 struct objprop *op,
2383 union packetdata pd)
2384{
2385 struct propval *pv;
2388
2389 if (!op || !ob || !pd.pointers.v_pointer1) {
2390 return;
2391 }
2392
2393 if (NULL == objbind_get_object(ob)) {
2394 return;
2395 }
2396
2398 return;
2399 }
2400
2402 if (!pv) {
2403 return;
2404 }
2405
2408
2409 switch (objtype) {
2410 case OBJTYPE_TILE:
2411 {
2412 struct packet_edit_tile *packet = pd.tile;
2413
2414 switch (propid) {
2415 case OPID_TILE_SPECIALS:
2417 if (BV_ISSET(pv->data.v_bv_special, pextra->data.special_idx)) {
2418 BV_SET(packet->extras, pextra->data.special_idx);
2419 } else {
2420 BV_CLR(packet->extras, pextra->data.special_idx);
2421 }
2423 return;
2424 case OPID_TILE_ROADS:
2426 int ridx = road_number(extra_road_get(pextra));
2427
2428 if (BV_ISSET(pv->data.v_bv_roads, ridx)) {
2429 BV_SET(packet->extras, extra_index(pextra));
2430 } else {
2431 BV_CLR(packet->extras, extra_index(pextra));
2432 }
2434 return;
2435 case OPID_TILE_BASES:
2437 int bidx = base_number(extra_base_get(pextra));
2438
2439 if (BV_ISSET(pv->data.v_bv_bases, bidx)) {
2440 BV_SET(packet->extras, extra_index(pextra));
2441 } else {
2442 BV_CLR(packet->extras, extra_index(pextra));
2443 }
2445 return;
2446 case OPID_TILE_LABEL:
2447 sz_strlcpy(packet->label, pv->data.v_string);
2448 return;
2449 default:
2450 break;
2451 }
2452 }
2453 log_error("%s(): Unhandled request to pack value of property "
2454 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2456 return;
2457
2458 case OBJTYPE_STARTPOS:
2459 {
2460 struct packet_edit_startpos_full *packet = pd.startpos;
2461
2462 switch (propid) {
2464 packet->exclude = pv->data.v_bool;
2465 return;
2467 BV_CLR_ALL(packet->nations);
2468 nation_hash_iterate(pv->data.v_nation_hash, pnation) {
2469 BV_SET(packet->nations, nation_number(pnation));
2471 return;
2472 default:
2473 break;
2474 }
2475 }
2476 log_error("%s(): Unhandled request to pack value of property "
2477 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2479 return;
2480
2481 case OBJTYPE_UNIT:
2482 {
2483 struct packet_edit_unit *packet = pd.unit;
2484
2485 switch (propid) {
2487 packet->moves_left = pv->data.v_int;
2488 return;
2489 case OPID_UNIT_FUEL:
2490 packet->fuel = pv->data.v_int;
2491 return;
2492 case OPID_UNIT_MOVED:
2493 packet->moved = pv->data.v_bool;
2494 return;
2496 packet->done_moving = pv->data.v_bool;
2497 return;
2498 case OPID_UNIT_HP:
2499 packet->hp = pv->data.v_int;
2500 return;
2501 case OPID_UNIT_VETERAN:
2502 packet->veteran = pv->data.v_int;
2503 return;
2504 case OPID_UNIT_STAY:
2505 packet->stay = pv->data.v_bool;
2506 return;
2507 default:
2508 break;
2509 }
2510 }
2511 log_error("%s(): Unhandled request to pack value of property "
2512 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2514 return;
2515
2516 case OBJTYPE_CITY:
2517 {
2518 struct packet_edit_city *packet = pd.city;
2519
2520 switch (propid) {
2521 case OPID_CITY_NAME:
2522 sz_strlcpy(packet->name, pv->data.v_string);
2523 return;
2524 case OPID_CITY_SIZE:
2525 packet->size = pv->data.v_int;
2526 return;
2527 case OPID_CITY_HISTORY:
2528 packet->history = pv->data.v_int;
2529 return;
2531 packet->food_stock = pv->data.v_int;
2532 return;
2534 packet->shield_stock = pv->data.v_int;
2535 return;
2537 {
2538 int i;
2539
2540 for (i = 0; i < B_LAST; i++) {
2541 packet->built[i] = pv->data.v_built[i].turn;
2542 }
2543 }
2544 return;
2545 default:
2546 break;
2547 }
2548 }
2549 log_error("%s(): Unhandled request to pack value of property "
2550 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2552 return;
2553
2554 case OBJTYPE_PLAYER:
2555 {
2556 struct packet_edit_player *packet = pd.player;
2557
2558 switch (propid) {
2559 case OPID_PLAYER_NAME:
2560 sz_strlcpy(packet->name, pv->data.v_string);
2561 return;
2562 case OPID_PLAYER_NATION:
2563 packet->nation = nation_index(pv->data.v_nation);
2564 return;
2565 case OPID_PLAYER_GOV:
2566 packet->government = government_index(pv->data.v_gov);
2567 return;
2570 packet->inventions[tech] = BV_ISSET(pv->data.v_bv_inventions, tech);
2572 return;
2574 packet->scenario_reserved = pv->data.v_bool;
2575 return;
2577 packet->autoselect_weight = pv->data.v_int;
2578 return;
2580 packet->bulbs_researched = pv->data.v_int;
2581 return;
2582 case OPID_PLAYER_GOLD:
2583 packet->gold = pv->data.v_int;
2584 return;
2586 packet->infrapoints = pv->data.v_int;
2587 return;
2588 default:
2589 break;
2590 }
2591 }
2592 log_error("%s(): Unhandled request to pack value of property "
2593 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2595 return;
2596
2597 case OBJTYPE_GAME:
2598 {
2599 struct packet_edit_game *packet = pd.game.game;
2600
2601 switch (propid) {
2602 case OPID_GAME_SCENARIO:
2603 packet->scenario = pv->data.v_bool;
2604 return;
2606 sz_strlcpy(packet->scenario_name, pv->data.v_const_string);
2607 return;
2609 sz_strlcpy(packet->scenario_authors, pv->data.v_const_string);
2610 return;
2612 sz_strlcpy(pd.game.desc->scenario_desc, pv->data.v_const_string);
2613 return;
2615 packet->scenario_random = pv->data.v_bool;
2616 return;
2618 packet->scenario_players = pv->data.v_bool;
2619 return;
2621 packet->startpos_nations = pv->data.v_bool;
2622 return;
2624 packet->prevent_new_cities = pv->data.v_bool;
2625 return;
2627 packet->lake_flooding = pv->data.v_bool;
2628 return;
2630 packet->ruleset_locked = pv->data.v_bool;
2631 return;
2632 default:
2633 break;
2634 }
2635 }
2636 log_error("%s(): Unhandled request to pack value of property "
2637 "%d (%s) from object of type \"%s\".", __FUNCTION__,
2639 return;
2640
2641 case NUM_OBJTYPES:
2642 break;
2643 }
2644
2645 log_error("%s(): Unhandled request for object type \"%s\" (nb %d).",
2647
2648}
2649
2650/************************************************************************/
2653static void objbind_set_rowref(struct objbind *ob,
2655{
2656 if (!ob) {
2657 return;
2658 }
2659 ob->rowref = rr;
2660}
2661
2662/************************************************************************/
2666{
2667 if (!ob) {
2668 return NULL;
2669 }
2670 return ob->rowref;
2671}
2672
2673/************************************************************************/
2676static int objprop_get_id(const struct objprop *op)
2677{
2678 if (!op) {
2679 return -1;
2680 }
2681 return op->id;
2682}
2683
2684/************************************************************************/
2691static GType objprop_get_gtype(const struct objprop *op)
2692{
2694
2695 switch (op->valtype) {
2696 case VALTYPE_NONE:
2698 return G_TYPE_NONE;
2699 case VALTYPE_INT:
2700 return G_TYPE_INT;
2701 case VALTYPE_BOOL:
2702 /* We want to show it as translated string, not as untranslated G_TYPE_BOOLEAN */
2703 return G_TYPE_STRING;
2704 case VALTYPE_STRING:
2707 case VALTYPE_BV_SPECIAL:
2708 case VALTYPE_BV_ROADS:
2709 case VALTYPE_BV_BASES:
2711 return G_TYPE_STRING;
2712 case VALTYPE_PIXBUF:
2713 case VALTYPE_NATION:
2714 case VALTYPE_GOV:
2715 return GDK_TYPE_PIXBUF;
2716 }
2717 log_error("%s(): Unhandled value type %d.", __FUNCTION__, op->valtype);
2718 return G_TYPE_NONE;
2719}
2720
2721/************************************************************************/
2724static enum value_types objprop_get_valtype(const struct objprop *op)
2725{
2726 if (!op) {
2727 return VALTYPE_NONE;
2728 }
2729 return op->valtype;
2730}
2731
2732/************************************************************************/
2735static bool objprop_show_in_listview(const struct objprop *op)
2736{
2737 if (!op) {
2738 return FALSE;
2739 }
2740 return op->flags & OPF_IN_LISTVIEW;
2741}
2742
2743/************************************************************************/
2746static bool objprop_has_widget(const struct objprop *op)
2747{
2748 if (!op) {
2749 return FALSE;
2750 }
2751 return op->flags & OPF_HAS_WIDGET;
2752}
2753
2754/************************************************************************/
2760static const char *objprop_get_attribute_type_string(const struct objprop *op)
2761{
2762 GType gtype;
2763
2764 if (!op) {
2765 return NULL;
2766 }
2767
2769 if (gtype == G_TYPE_INT || gtype == G_TYPE_STRING
2770 || gtype == G_TYPE_BOOLEAN) {
2771 return "text";
2772 } else if (gtype == GDK_TYPE_PIXBUF) {
2773 return "pixbuf";
2774 }
2775
2776 return NULL;
2777}
2778
2779/************************************************************************/
2785static void objprop_set_column_id(struct objprop *op, int col_id)
2786{
2787 if (!op) {
2788 return;
2789 }
2790 op->column_id = col_id;
2791}
2792
2793/************************************************************************/
2798static int objprop_get_column_id(const struct objprop *op)
2799{
2800 if (!op) {
2801 return -1;
2802 }
2803 return op->column_id;
2804}
2805
2806/************************************************************************/
2811{
2812 if (!op) {
2813 return;
2814 }
2815 op->view_column = col;
2816}
2817
2818/************************************************************************/
2823{
2824 if (!op) {
2825 return NULL;
2826 }
2827 return op->view_column;
2828}
2829
2830/************************************************************************/
2833static const char *objprop_get_name(const struct objprop *op)
2834{
2835 if (!op) {
2836 return NULL;
2837 }
2838 return op->name;
2839}
2840
2841/************************************************************************/
2844static const char *objprop_get_tooltip(const struct objprop *op)
2845{
2846 if (!op) {
2847 return NULL;
2848 }
2849 return op->tooltip;
2850}
2851
2852/************************************************************************/
2858{
2860 GType gtype;
2861
2863
2864 if (gtype == G_TYPE_INT || gtype == G_TYPE_STRING
2865 || gtype == G_TYPE_BOOLEAN) {
2867 } else if (gtype == GDK_TYPE_PIXBUF) {
2869 }
2870
2871 return cell;
2872}
2873
2874/************************************************************************/
2878static bool objprop_is_sortable(const struct objprop *op)
2879{
2880 GType gtype;
2881 if (!op) {
2882 return FALSE;
2883 }
2885 return gtype == G_TYPE_INT || gtype == G_TYPE_STRING;
2886}
2887
2888/************************************************************************/
2892static bool objprop_is_readonly(const struct objprop *op)
2893{
2894 if (!op) {
2895 return TRUE;
2896 }
2897 return !(op->flags & OPF_EDITABLE);
2898}
2899
2900/************************************************************************/
2904{
2905 struct objprop *op;
2906 struct property_page *pp;
2907 struct propval value = {{0,}, VALTYPE_STRING, FALSE};
2908
2909 op = userdata;
2912
2914}
2915
2916/************************************************************************/
2921{
2922 struct objprop *op;
2923 struct property_page *pp;
2924 struct propval value = {{0,}, VALTYPE_INT, FALSE};
2925
2926 op = userdata;
2929
2931}
2932
2933/************************************************************************/
2938{
2939 struct objprop *op;
2940 struct property_page *pp;
2941 struct propval value = {{0,}, VALTYPE_BOOL, FALSE};
2942
2943 op = userdata;
2946
2948}
2949
2950/************************************************************************/
2953static void objprop_setup_widget(struct objprop *op)
2954{
2955 GtkWidget *hbox, *hbox2, *label, *image, *text, *spin, *button;
2956 struct extviewer *ev = NULL;
2958
2959 if (!op) {
2960 return;
2961 }
2962
2963 if (!objprop_has_widget(op)) {
2964 return;
2965 }
2966
2968 op->widget = hbox;
2969
2973 gtk_box_append(GTK_BOX(hbox), label);
2974 objprop_set_child_widget(op, "name-label", label);
2975
2977
2978 switch (propid) {
2979 case OPID_TILE_INDEX:
2980 case OPID_TILE_X:
2981 case OPID_TILE_Y:
2982 case OPID_TILE_NAT_X:
2983 case OPID_TILE_NAT_Y:
2985 case OPID_TILE_TERRAIN:
2986 case OPID_TILE_RESOURCE:
2987 case OPID_TILE_XY:
2988 case OPID_STARTPOS_XY:
2989 case OPID_UNIT_ID:
2990 case OPID_UNIT_XY:
2991 case OPID_UNIT_TYPE:
2992 case OPID_CITY_ID:
2993 case OPID_CITY_XY:
2994 case OPID_PLAYER_AGE:
2995#ifdef FREECIV_DEBUG
2996 case OPID_TILE_ADDRESS:
2997 case OPID_UNIT_ADDRESS:
2998 case OPID_CITY_ADDRESS:
3000#endif /* FREECIV_DEBUG */
3001 label = gtk_label_new(NULL);
3005 gtk_box_append(GTK_BOX(hbox), label);
3006 objprop_set_child_widget(op, "value-label", label);
3007 return;
3008
3009 case OPID_TILE_IMAGE:
3011 case OPID_UNIT_IMAGE:
3012 case OPID_CITY_IMAGE:
3013 image = gtk_image_new();
3022 return;
3023
3024 case OPID_CITY_NAME:
3025 case OPID_PLAYER_NAME:
3027 case OPID_TILE_LABEL:
3028 text = gtk_text_new();
3032 g_signal_connect(text, "changed",
3034 gtk_box_append(GTK_BOX(hbox), text);
3035 objprop_set_child_widget(op, "text", text);
3036 return;
3037
3039 case OPID_CITY_SIZE:
3040 case OPID_CITY_HISTORY:
3044 case OPID_PLAYER_GOLD:
3046 spin = gtk_spin_button_new_with_range(0.0, 100.0, 1.0);
3049 g_signal_connect(spin, "value-changed",
3053 return;
3054
3055 case OPID_UNIT_FUEL:
3056 case OPID_UNIT_HP:
3057 case OPID_UNIT_VETERAN:
3063 spin = gtk_spin_button_new_with_range(0.0, 100.0, 1.0);
3064 g_signal_connect(spin, "value-changed",
3068 label = gtk_label_new(NULL);
3071 gtk_box_append(GTK_BOX(hbox2), label);
3072 objprop_set_child_widget(op, "max-value-label", label);
3073 return;
3074
3075 case OPID_TILE_SPECIALS:
3076 case OPID_TILE_ROADS:
3077 case OPID_TILE_BASES:
3078 case OPID_TILE_VISION:
3081 case OPID_PLAYER_NATION:
3082 case OPID_PLAYER_GOV:
3086 ev = extviewer_new(op);
3092 return;
3093
3095 case OPID_UNIT_MOVED:
3097 case OPID_UNIT_STAY:
3098 case OPID_GAME_SCENARIO:
3106 button = gtk_toggle_button_new();
3109 g_signal_connect(button, "toggled",
3111 op);
3112 gtk_box_append(GTK_BOX(hbox), button);
3113 objprop_set_child_widget(op, "togglebutton", button);
3114 return;
3115 }
3116
3117 log_error("%s(): Unhandled request to create widget for property %d (%s).",
3119}
3120
3121/************************************************************************/
3130 struct objbind *ob)
3131{
3132 GtkWidget *w, *label, *image, *text, *spin, *button;
3133 struct extviewer *ev;
3134 struct propval *pv;
3135 bool modified;
3137 double min, max, step, big_step;
3138 char buf[256];
3139 const char *newtext;
3140 GtkEntryBuffer *buffer;
3141
3142 if (!op || !objprop_has_widget(op)) {
3143 return;
3144 }
3145
3147 if (!w) {
3148 return;
3149 }
3150
3152
3153 /* NB: We must take care to propval_free() the return value of
3154 * objbind_get_value_from_object(), since it always makes a
3155 * copy, but to NOT free the result of objbind_get_modified_value()
3156 * since it returns its own stored value. */
3159
3160 if (pv && modified) {
3161 struct propval *pv_mod;
3162
3164 if (pv_mod) {
3165 if (propval_equal(pv, pv_mod)) {
3167 modified = FALSE;
3168 } else {
3170 pv = pv_mod;
3171 modified = TRUE;
3172 }
3173 } else {
3174 modified = FALSE;
3175 }
3176 }
3177
3178 switch (propid) {
3179 case OPID_TILE_IMAGE:
3181 case OPID_UNIT_IMAGE:
3182 case OPID_CITY_IMAGE:
3183 image = objprop_get_child_widget(op, "image");
3184 if (pv) {
3185 gtk_image_set_from_pixbuf(GTK_IMAGE(image), pv->data.v_pixbuf);
3186 } else {
3188 }
3189 break;
3190
3191 case OPID_TILE_XY:
3192 case OPID_TILE_TERRAIN:
3193 case OPID_TILE_RESOURCE:
3194 case OPID_STARTPOS_XY:
3195 case OPID_UNIT_XY:
3196 case OPID_UNIT_TYPE:
3197 case OPID_CITY_XY:
3198#ifdef FREECIV_DEBUG
3199 case OPID_TILE_ADDRESS:
3200 case OPID_UNIT_ADDRESS:
3201 case OPID_CITY_ADDRESS:
3203#endif /* FREECIV_DEBUG */
3204 label = objprop_get_child_widget(op, "value-label");
3205 if (pv) {
3206 gtk_label_set_text(GTK_LABEL(label), pv->data.v_string);
3207 } else {
3209 }
3210 break;
3211
3212 case OPID_TILE_INDEX:
3213 case OPID_TILE_X:
3214 case OPID_TILE_Y:
3215 case OPID_TILE_NAT_X:
3216 case OPID_TILE_NAT_Y:
3218 case OPID_UNIT_ID:
3219 case OPID_CITY_ID:
3220 case OPID_PLAYER_AGE:
3221 label = objprop_get_child_widget(op, "value-label");
3222 if (pv) {
3223 char agebuf[16];
3224
3225 fc_snprintf(agebuf, sizeof(agebuf), "%d", pv->data.v_int);
3227 } else {
3229 }
3230 break;
3231
3232 case OPID_CITY_NAME:
3233 case OPID_PLAYER_NAME:
3235 case OPID_TILE_LABEL:
3236 text = objprop_get_child_widget(op, "text");
3237 if (pv) {
3238 /* Most of these are semantically in "v_const_string",
3239 * but this works as the address is the same regardless. */
3240 newtext = pv->data.v_string;
3241 } else {
3242 newtext = "";
3243 }
3244 buffer = gtk_text_get_buffer(GTK_TEXT(text));
3245
3246 /* Only set the text if it has changed. This breaks
3247 * recursive loop. */
3250 }
3252 break;
3253
3255 case OPID_CITY_SIZE:
3256 case OPID_CITY_HISTORY:
3260 case OPID_PLAYER_GOLD:
3262 spin = objprop_get_child_widget(op, "spin");
3263 if (pv) {
3266 if (objbind_get_allowed_value_span(ob, op, &min, &max,
3267 &step, &big_step)) {
3270 step, big_step);
3271 }
3275 }
3277 break;
3278
3279 case OPID_UNIT_FUEL:
3280 case OPID_UNIT_HP:
3281 case OPID_UNIT_VETERAN:
3283 spin = objprop_get_child_widget(op, "spin");
3284 label = objprop_get_child_widget(op, "max-value-label");
3285 if (pv) {
3288 if (objbind_get_allowed_value_span(ob, op, &min, &max,
3289 &step, &big_step)) {
3292 step, big_step);
3293 fc_snprintf(buf, sizeof(buf), "/%d", (int) max);
3295 } else {
3297 }
3301 } else {
3303 }
3305 break;
3306
3307 case OPID_TILE_SPECIALS:
3308 case OPID_TILE_ROADS:
3309 case OPID_TILE_BASES:
3310 case OPID_TILE_VISION:
3313 case OPID_PLAYER_NATION:
3314 case OPID_PLAYER_GOV:
3319 if (pv) {
3321 } else {
3323 }
3324 break;
3325
3327 case OPID_UNIT_MOVED:
3329 case OPID_UNIT_STAY:
3330 case OPID_GAME_SCENARIO:
3338 button = objprop_get_child_widget(op, "togglebutton");
3341 if (pv) {
3343 pv->data.v_bool);
3344 } else {
3346 }
3349 gtk_widget_set_sensitive(button, pv != NULL);
3350 break;
3351 }
3352
3353 if (!modified) {
3355 }
3356
3357 label = objprop_get_child_widget(op, "name-label");
3358 if (label) {
3359 const char *name = objprop_get_name(op);
3360 if (modified) {
3361 char namebuf[128];
3362
3363 fc_snprintf(namebuf, sizeof(namebuf),
3364 "<span foreground=\"red\">%s</span>", name);
3366 } else {
3368 }
3369 }
3370}
3371
3372/************************************************************************/
3377{
3378 if (!op) {
3379 return NULL;
3380 }
3381 if (!op->widget) {
3383 }
3384 return op->widget;
3385}
3386
3387/************************************************************************/
3392 const char *widget_name,
3394{
3395 GtkWidget *w;
3396
3397 if (!op || !widget_name || !widget) {
3398 return;
3399 }
3400
3402 if (!w) {
3403 log_error("Cannot store child widget %p under name "
3404 "\"%s\" using objprop_set_child_widget for object "
3405 "property %d (%s) because objprop_get_widget does "
3406 "not return a valid widget.",
3408 return;
3409 }
3410
3412}
3413
3414/************************************************************************/
3419 const char *widget_name)
3420{
3421 GtkWidget *w, *child;
3422
3423 if (!op || !widget_name) {
3424 return NULL;
3425 }
3426
3428 if (!w) {
3429 log_error("Cannot retrieve child widget under name "
3430 "\"%s\" using objprop_get_child_widget for object "
3431 "property %d (%s) because objprop_get_widget does "
3432 "not return a valid widget.",
3434 return NULL;
3435 }
3436
3438 if (!child) {
3439 log_error("Child widget \"%s\" not found for object "
3440 "property %d (%s) via objprop_get_child_widget.",
3442 return NULL;
3443 }
3444
3445 return child;
3446}
3447
3448/************************************************************************/
3452 struct extviewer *ev)
3453{
3454 if (!op) {
3455 return;
3456 }
3457 op->extviewer = ev;
3458}
3459
3460/************************************************************************/
3464{
3465 if (!op) {
3466 return NULL;
3467 }
3468 return op->extviewer;
3469}
3470
3471/************************************************************************/
3475{
3476 if (!op) {
3477 return NULL;
3478 }
3479 return op->parent_page;
3480}
3481
3482/************************************************************************/
3485static struct objprop *objprop_new(int id,
3486 const char *name,
3487 const char *tooltip,
3489 enum value_types valtype,
3490 struct property_page *parent)
3491{
3492 struct objprop *op;
3493
3494 op = fc_calloc(1, sizeof(*op));
3495 op->id = id;
3496 op->name = name;
3497 op->tooltip = tooltip;
3498 op->flags = flags;
3499 op->valtype = valtype;
3500 op->column_id = -1;
3501 op->parent_page = parent;
3502
3503 return op;
3504}
3505
3506/************************************************************************/
3510static struct extviewer *extviewer_new(struct objprop *op)
3511{
3512 struct extviewer *ev;
3513 GtkWidget *hbox, *vbox, *label, *button, *scrollwin, *image;
3514 GtkWidget *view = NULL;
3518 GType *gtypes;
3520 int num_cols;
3521
3522 if (!op) {
3523 return NULL;
3524 }
3525
3526 ev = fc_calloc(1, sizeof(*ev));
3527 ev->objprop = op;
3528
3530
3531
3532 /* Create the panel widget. */
3533
3534 switch (propid) {
3535 case OPID_TILE_SPECIALS:
3536 case OPID_TILE_ROADS:
3537 case OPID_TILE_BASES:
3544 ev->panel_widget = hbox;
3545
3546 label = gtk_label_new(NULL);
3549 gtk_box_append(GTK_BOX(hbox), label);
3550 ev->panel_label = label;
3551 break;
3552
3553 case OPID_PLAYER_NATION:
3554 case OPID_PLAYER_GOV:
3556 ev->panel_widget = vbox;
3557
3558 label = gtk_label_new(NULL);
3561 gtk_box_append(GTK_BOX(vbox), label);
3562 ev->panel_label = label;
3563
3565 gtk_box_append(GTK_BOX(vbox), hbox);
3566
3567 image = gtk_image_new();
3568 if (propid == OPID_PLAYER_GOV) {
3572 } else {
3573 /* propid OPID_PLAYER_NATION */
3575 }
3579 ev->panel_image = image;
3580 break;
3581
3582 case OPID_TILE_VISION:
3584 ev->panel_widget = hbox;
3585 break;
3586
3587 default:
3588 log_error("Unhandled request to create panel widget "
3589 "for property %d (%s) in extviewer_new().",
3592 ev->panel_widget = hbox;
3593 break;
3594 }
3595
3596 if (objprop_is_readonly(op)) {
3597 button = gtk_button_new_with_label(Q_("?verb:View"));
3598 } else {
3599 button = gtk_button_new_with_label(_("Edit"));
3600 }
3601 g_signal_connect(button, "clicked",
3603 gtk_box_append(GTK_BOX(hbox), button);
3604 ev->panel_button = button;
3605
3606
3607 /* Create the data store. */
3608
3609 switch (propid) {
3610 case OPID_TILE_SPECIALS:
3611 case OPID_TILE_ROADS:
3612 case OPID_TILE_BASES:
3616 break;
3617 case OPID_TILE_VISION:
3618 num_cols = 3 + 1 + V_COUNT;
3619 gtypes = fc_malloc(num_cols * sizeof(GType));
3620 gtypes[0] = G_TYPE_INT; /* player number */
3621 gtypes[1] = GDK_TYPE_PIXBUF; /* player flag */
3622 gtypes[2] = G_TYPE_STRING; /* player name */
3623 gtypes[3] = G_TYPE_BOOLEAN; /* tile_known */
3625 gtypes[4 + v] = G_TYPE_BOOLEAN; /* tile_seen[v] */
3628 free(gtypes);
3629 break;
3633 break;
3635 case OPID_PLAYER_NATION:
3636 case OPID_PLAYER_GOV:
3639 break;
3643 break;
3644 default:
3645 log_error("Unhandled request to create data store "
3646 "for property %d (%s) in extviewer_new().",
3648 break;
3649 }
3650
3651 ev->store = store;
3652 ev->textbuf = textbuf;
3653
3654 /* Create the view widget. */
3655
3657 ev->view_widget = vbox;
3658
3662 gtk_box_append(GTK_BOX(vbox), label);
3663 ev->view_label = label;
3664
3665 if (store || textbuf) {
3668 TRUE);
3673
3674 if (store) {
3678 } else {
3679 const bool editable = !objprop_is_readonly(op);
3680
3684 }
3687
3689 }
3690
3691 switch (propid) {
3692
3693 case OPID_TILE_SPECIALS:
3694 case OPID_TILE_ROADS:
3695 case OPID_TILE_BASES:
3696 /* TRANS: As in "this tile special is present". */
3697 add_column(view, 0, _("Present"), G_TYPE_BOOLEAN, TRUE, FALSE,
3699 add_column(view, 1, _("ID"), G_TYPE_INT,
3700 FALSE, FALSE, NULL, NULL);
3701 add_column(view, 2, _("Name"), G_TYPE_STRING,
3702 FALSE, FALSE, NULL, NULL);
3703 break;
3704
3705 case OPID_TILE_VISION:
3706 add_column(view, 0, _("ID"), G_TYPE_INT,
3707 FALSE, FALSE, NULL, NULL);
3708 add_column(view, 1, _("Nation"), GDK_TYPE_PIXBUF,
3709 FALSE, FALSE, NULL, NULL);
3710 add_column(view, 2, _("Name"), G_TYPE_STRING,
3711 FALSE, FALSE, NULL, NULL);
3712 add_column(view, 3, _("Known"), G_TYPE_BOOLEAN,
3713 FALSE, FALSE, NULL, NULL);
3718 break;
3719
3721 /* TRANS: As in "this building is present". */
3722 add_column(view, 0, _("Present"), G_TYPE_BOOLEAN, TRUE, FALSE,
3724 add_column(view, 1, _("ID"), G_TYPE_INT,
3725 FALSE, FALSE, NULL, NULL);
3726 add_column(view, 2, _("Name"), G_TYPE_STRING,
3727 FALSE, FALSE, NULL, NULL);
3728 /* TRANS: As in "the turn when this building was built". */
3729 add_column(view, 3, _("Turn Built"), G_TYPE_STRING,
3730 FALSE, FALSE, NULL, NULL);
3731 break;
3732
3734 /* TRANS: As in "the player has set this nation". */
3735 add_column(view, 0, _("Set"), G_TYPE_BOOLEAN, TRUE, FALSE,
3737 add_column(view, 1, _("ID"), G_TYPE_INT,
3738 FALSE, FALSE, NULL, NULL);
3739 add_column(view, 2, _("Flag"), GDK_TYPE_PIXBUF,
3740 FALSE, FALSE, NULL, NULL);
3741 add_column(view, 3, _("Name"), G_TYPE_STRING,
3742 FALSE, FALSE, NULL, NULL);
3743 break;
3744
3745 case OPID_PLAYER_NATION:
3746 case OPID_PLAYER_GOV:
3747 /* TRANS: As in "the player has set this nation". */
3748 add_column(view, 0, _("Set"), G_TYPE_BOOLEAN, TRUE, TRUE,
3750 add_column(view, 1, _("ID"), G_TYPE_INT,
3751 FALSE, FALSE, NULL, NULL);
3752 add_column(view, 2,
3753 propid == OPID_PLAYER_GOV ? _("Icon") : _("Flag"),
3755 FALSE, FALSE, NULL, NULL);
3756 add_column(view, 3, _("Name"), G_TYPE_STRING,
3757 FALSE, FALSE, NULL, NULL);
3758 break;
3759
3761 /* TRANS: As in "this invention is known". */
3762 add_column(view, 0, _("Known"), G_TYPE_BOOLEAN, TRUE, FALSE,
3764 add_column(view, 1, _("ID"), G_TYPE_INT,
3765 FALSE, FALSE, NULL, NULL);
3766 add_column(view, 2, _("Name"), G_TYPE_STRING,
3767 FALSE, FALSE, NULL, NULL);
3768 break;
3769
3772 g_signal_connect(textbuf, "changed",
3774 break;
3775
3776 default:
3777 log_error("Unhandled request to configure view widget "
3778 "for property %d (%s) in extviewer_new().",
3780 break;
3781 }
3782
3783 gtk_widget_set_visible(ev->panel_widget, TRUE);
3784 gtk_widget_set_visible(ev->view_widget, TRUE);
3785
3786 return ev;
3787}
3788
3789/************************************************************************/
3793{
3794 if (!ev) {
3795 return NULL;
3796 }
3797 return ev->objprop;
3798}
3799
3800/************************************************************************/
3805{
3806 if (!ev) {
3807 return NULL;
3808 }
3809 return ev->panel_widget;
3810}
3811
3812/************************************************************************/
3817{
3818 if (!ev) {
3819 return NULL;
3820 }
3821 return ev->view_widget;
3822}
3823
3824/************************************************************************/
3828 struct propval *pv)
3829{
3830 struct objprop *op;
3832 int id, turn_built;
3833 bool present, all;
3834 const char *name;
3836 GtkListStore *store;
3837 GtkTextBuffer *textbuf;
3839 gchar *buf;
3840
3841 if (!ev) {
3842 return;
3843 }
3844
3847
3848 if (propval_equal(pv, ev->pv_cached)) {
3849 return;
3850 }
3851 propval_free(ev->pv_cached);
3852 ev->pv_cached = propval_copy(pv);
3853 store = ev->store;
3854 textbuf = ev->textbuf;
3855
3856
3857 /* NB: Remember to have -1 as the last argument to
3858 * gtk_list_store_set() and to use the correct column
3859 * number when inserting data. :) */
3860 switch (propid) {
3861
3862 case OPID_TILE_SPECIALS:
3863 gtk_list_store_clear(store);
3865 id = spe->data.special_idx;
3867 present = BV_ISSET(pv->data.v_bv_special, id);
3868 gtk_list_store_append(store, &iter);
3869 gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name, -1);
3872 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
3873 g_free(buf);
3874 break;
3875
3876 case OPID_TILE_ROADS:
3877 gtk_list_store_clear(store);
3879 struct road_type *proad = extra_road_get(pextra);
3880
3881 id = road_number(proad);
3882 name = extra_name_translation(pextra);
3883 present = BV_ISSET(pv->data.v_bv_roads, id);
3884 gtk_list_store_append(store, &iter);
3885 gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name, -1);
3888 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
3889 g_free(buf);
3890 break;
3891
3892 case OPID_TILE_BASES:
3893 gtk_list_store_clear(store);
3895 struct base_type *pbase = extra_base_get(pextra);
3896
3897 id = base_number(pbase);
3898 name = extra_name_translation(pextra);
3899 present = BV_ISSET(pv->data.v_bv_bases, id);
3900 gtk_list_store_append(store, &iter);
3901 gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name, -1);
3904 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
3905 g_free(buf);
3906 break;
3907
3908 case OPID_TILE_VISION:
3909 gtk_list_store_clear(store);
3910 player_slots_iterate(pslot) {
3911 id = player_slot_index(pslot);
3912 if (player_slot_is_used(pslot)) {
3913 struct player *pplayer = player_slot_get_player(pslot);
3914
3915 name = player_name(pplayer);
3916 pixbuf = get_flag(pplayer->nation);
3917 } else {
3918 name = "";
3919 pixbuf = NULL;
3920 }
3921 gtk_list_store_append(store, &iter);
3922 gtk_list_store_set(store, &iter, 0, id, 2, name, -1);
3923 if (pixbuf) {
3924 gtk_list_store_set(store, &iter, 1, pixbuf, -1);
3926 pixbuf = NULL;
3927 }
3928 present = BV_ISSET(pv->data.v_tile_vision->tile_known, id);
3929 gtk_list_store_set(store, &iter, 3, present, -1);
3931 present = BV_ISSET(pv->data.v_tile_vision->tile_seen[v], id);
3932 gtk_list_store_set(store, &iter, 4 + v, present, -1);
3935 break;
3936
3938 gtk_list_store_clear(store);
3939 gtk_list_store_append(store, &iter);
3940 all = (0 == nation_hash_size(pv->data.v_nation_hash));
3941 gtk_list_store_set(store, &iter, 0, all, 1, -1, 3,
3942 _("All nations"), -1);
3943 nations_iterate(pnation) {
3945 && is_nation_playable(pnation)) {
3946 present = (!all && nation_hash_lookup(pv->data.v_nation_hash,
3947 pnation, NULL));
3948 id = nation_number(pnation);
3949 pixbuf = get_flag(pnation);
3951 gtk_list_store_append(store, &iter);
3952 gtk_list_store_set(store, &iter, 0, present, 1, id,
3953 2, pixbuf, 3, name, -1);
3954 if (pixbuf) {
3956 }
3957 }
3960 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
3961 g_free(buf);
3962 break;
3963
3965 gtk_list_store_clear(store);
3966 improvement_iterate(pimprove) {
3967 if (is_special_improvement(pimprove)) {
3968 continue;
3969 }
3970 id = improvement_index(pimprove);
3972 turn_built = pv->data.v_built[id].turn;
3973 present = turn_built >= 0;
3974 buf = built_status_to_string(&pv->data.v_built[id]);
3975 gtk_list_store_append(store, &iter);
3976 gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name,
3977 3, buf, -1);
3978 g_free(buf);
3981 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
3982 g_free(buf);
3983 break;
3984
3985 case OPID_PLAYER_NATION:
3986 {
3987 enum barbarian_type barbarian_type =
3988 nation_barbarian_type(pv->data.v_nation);
3989
3990 gtk_list_store_clear(store);
3991 nations_iterate(pnation) {
3993 && nation_barbarian_type(pnation) == barbarian_type
3994 && (barbarian_type != NOT_A_BARBARIAN
3995 || is_nation_playable(pnation))) {
3996 present = (pnation == pv->data.v_nation);
3997 id = nation_index(pnation);
3998 pixbuf = get_flag(pnation);
4000 gtk_list_store_append(store, &iter);
4001 gtk_list_store_set(store, &iter, 0, present, 1, id,
4002 2, pixbuf, 3, name, -1);
4003 if (pixbuf) {
4005 }
4006 }
4008 gtk_label_set_text(GTK_LABEL(ev->panel_label),
4009 nation_adjective_translation(pv->data.v_nation));
4010 pixbuf = get_flag(pv->data.v_nation);
4012 if (pixbuf) {
4014 }
4015 }
4016 break;
4017
4018 case OPID_PLAYER_GOV:
4019 {
4020 gtk_list_store_clear(store);
4022 present = (pgov == pv->data.v_gov);
4023 id = government_index(pgov);
4026 gtk_list_store_append(store, &iter);
4027 gtk_list_store_set(store, &iter, 0, present, 1, id,
4028 2, pixbuf, 3, name, -1);
4029 if (pixbuf) {
4031 }
4033 if (pv->data.v_gov != NULL) {
4034 gtk_label_set_text(GTK_LABEL(ev->panel_label),
4035 government_name_translation(pv->data.v_gov));
4037 } else {
4038 gtk_label_set_text(GTK_LABEL(ev->panel_label), "?");
4041 }
4042
4044 if (pixbuf) {
4046 }
4047 }
4048 break;
4049
4051 gtk_list_store_clear(store);
4053 id = advance_index(padvance);
4054 present = BV_ISSET(pv->data.v_bv_inventions, id);
4056 gtk_list_store_append(store, &iter);
4057 gtk_list_store_set(store, &iter, 0, present, 1, id, 2, name, -1);
4060 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4061 g_free(buf);
4062 break;
4063
4068 {
4069 GtkTextIter start, end;
4070 char *oldtext;
4071
4072 /* Don't re-set content if unchanged, to avoid moving cursor */
4073 gtk_text_buffer_get_bounds(textbuf, &start, &end);
4074 oldtext = gtk_text_buffer_get_text(textbuf, &start, &end, TRUE);
4075 if (strcmp(oldtext, pv->data.v_const_string) != 0) {
4076 gtk_text_buffer_set_text(textbuf, pv->data.v_const_string, -1);
4077 }
4078 }
4081 gtk_widget_set_sensitive(ev->view_widget, TRUE);
4083 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4084 g_free(buf);
4085 break;
4086
4087 default:
4088 log_error("Unhandled request to refresh widgets "
4089 "extviewer_refresh_widgets() for objprop id=%d "
4090 "name \"%s\".", propid, objprop_get_name(op));
4091 break;
4092 }
4093}
4094
4095/************************************************************************/
4099{
4100 struct objprop *op;
4102
4103 if (!ev) {
4104 return;
4105 }
4106
4109
4110 propval_free(ev->pv_cached);
4111 ev->pv_cached = NULL;
4112
4113 if (ev->panel_label != NULL) {
4114 gtk_label_set_text(GTK_LABEL(ev->panel_label), NULL);
4115 }
4116
4117 switch (propid) {
4118 case OPID_TILE_SPECIALS:
4119 case OPID_TILE_ROADS:
4120 case OPID_TILE_BASES:
4121 case OPID_TILE_VISION:
4125 gtk_list_store_clear(ev->store);
4126 break;
4127 case OPID_PLAYER_NATION:
4128 case OPID_PLAYER_GOV:
4129 gtk_list_store_clear(ev->store);
4131 break;
4136 gtk_text_buffer_set_text(ev->textbuf, "", -1);
4139 gtk_widget_set_sensitive(ev->view_widget, FALSE);
4140 break;
4141 default:
4142 log_error("Unhandled request to clear widgets "
4143 "in extviewer_clear_widgets() for objprop id=%d "
4144 "name \"%s\".", propid, objprop_get_name(op));
4145 break;
4146 }
4147}
4148
4149/************************************************************************/
4155{
4156 struct extviewer *ev;
4157 struct property_page *pp;
4158 struct objprop *op;
4159
4160 ev = userdata;
4161 if (!ev) {
4162 return;
4163 }
4164
4168}
4169
4170/************************************************************************/
4174 gchar *path,
4176{
4177 struct extviewer *ev;
4178 struct objprop *op;
4179 struct property_page *pp;
4181 GtkTreeModel *model;
4183 int id, old_id, turn_built;
4184 struct propval *pv;
4185 bool active, present;
4186 gchar *buf;
4188
4189 ev = userdata;
4190 if (!ev) {
4191 return;
4192 }
4193
4194 pv = ev->pv_cached;
4195 if (!pv) {
4196 return;
4197 }
4198
4203
4204 model = GTK_TREE_MODEL(ev->store);
4205 if (!gtk_tree_model_get_iter_from_string(model, &iter, path)) {
4206 return;
4207 }
4208 present = !active;
4209
4210
4211 switch (propid) {
4212
4213 case OPID_TILE_SPECIALS:
4214 gtk_tree_model_get(model, &iter, 1, &id, -1);
4216 return;
4217 }
4218 if (present) {
4219 BV_SET(pv->data.v_bv_special, id);
4220 } else {
4221 BV_CLR(pv->data.v_bv_special, id);
4222 }
4223 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4225 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4226 g_free(buf);
4227 break;
4228
4229 case OPID_TILE_ROADS:
4230 gtk_tree_model_get(model, &iter, 1, &id, -1);
4231 if (!(0 <= id && id < road_count())) {
4232 return;
4233 }
4234 if (present) {
4235 BV_SET(pv->data.v_bv_roads, id);
4236 } else {
4237 BV_CLR(pv->data.v_bv_roads, id);
4238 }
4239 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4241 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4242 g_free(buf);
4243 break;
4244
4245 case OPID_TILE_BASES:
4246 gtk_tree_model_get(model, &iter, 1, &id, -1);
4247 if (!(0 <= id && id < base_count())) {
4248 return;
4249 }
4250 if (present) {
4251 BV_SET(pv->data.v_bv_bases, id);
4252 } else {
4253 BV_CLR(pv->data.v_bv_bases, id);
4254 }
4255 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4257 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4258 g_free(buf);
4259 break;
4260
4262 gtk_tree_model_get(model, &iter, 1, &id, -1);
4263 if (-1 > id && id >= nation_count()) {
4264 return;
4265 }
4266
4267 if (-1 == id) {
4268 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4270 if (present) {
4271 while (gtk_tree_model_iter_next(model, &iter)) {
4272 gtk_list_store_set(ev->store, &iter, 0, FALSE, -1);
4273 }
4274 nation_hash_clear(pv->data.v_nation_hash);
4275 } else {
4276 const struct nation_type *pnation;
4277 int id2;
4278
4280 gtk_tree_model_get(model, &iter, 0, &id2, -1);
4281 gtk_list_store_set(ev->store, &iter, 0, TRUE, -1);
4282 pnation = nation_by_number(id2);
4283 nation_hash_insert(pv->data.v_nation_hash, pnation, NULL);
4284 }
4285 } else {
4286 const struct nation_type *pnation;
4287 bool all;
4288
4289 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4290 pnation = nation_by_number(id);
4291 if (present) {
4292 nation_hash_insert(pv->data.v_nation_hash, pnation, NULL);
4293 } else {
4294 nation_hash_remove(pv->data.v_nation_hash, pnation);
4295 }
4297 all = (0 == nation_hash_size(pv->data.v_nation_hash));
4298 gtk_list_store_set(ev->store, &iter, 0, all, -1);
4299 }
4301 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4302 g_free(buf);
4303 break;
4304
4306 gtk_tree_model_get(model, &iter, 1, &id, -1);
4307 if (!(0 <= id && id < B_LAST)) {
4308 return;
4309 }
4310 turn_built = present ? game.info.turn : I_NEVER;
4311 pv->data.v_built[id].turn = turn_built;
4312 buf = built_status_to_string(&pv->data.v_built[id]);
4313 gtk_list_store_set(ev->store, &iter, 0, present, 3, buf, -1);
4314 g_free(buf);
4316 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4317 g_free(buf);
4318 break;
4319
4320 case OPID_PLAYER_NATION:
4321 gtk_tree_model_get(model, &iter, 1, &id, -1);
4322 if (!(0 <= id && id < nation_count()) || !present) {
4323 return;
4324 }
4325 old_id = nation_index(pv->data.v_nation);
4326 pv->data.v_nation = nation_by_number(id);
4327 gtk_list_store_set(ev->store, &iter, 0, TRUE, -1);
4329 gtk_list_store_set(ev->store, &iter, 0, FALSE, -1);
4330 gtk_label_set_text(GTK_LABEL(ev->panel_label),
4331 nation_adjective_translation(pv->data.v_nation));
4332 pixbuf = get_flag(pv->data.v_nation);
4334 if (pixbuf) {
4336 }
4337 break;
4338
4339 case OPID_PLAYER_GOV:
4340 gtk_tree_model_get(model, &iter, 1, &id, -1);
4341 if (!(0 <= id && id < government_count()) || !present) {
4342 return;
4343 }
4344 if (pv->data.v_gov != NULL) {
4345 old_id = government_index(pv->data.v_gov);
4346 pv->data.v_gov = government_by_number(id);
4347 gtk_list_store_set(ev->store, &iter, 0, TRUE, -1);
4349 gtk_list_store_set(ev->store, &iter, 0, FALSE, -1);
4350 } else {
4351 pv->data.v_gov = government_by_number(id);
4352 gtk_list_store_set(ev->store, &iter, 0, TRUE, -1);
4353 }
4354
4355 gtk_label_set_text(GTK_LABEL(ev->panel_label),
4356 government_name_translation(pv->data.v_gov));
4359 if (pixbuf) {
4361 }
4362 break;
4363
4365 gtk_tree_model_get(model, &iter, 1, &id, -1);
4366 if (!(A_FIRST <= id && id < advance_count())) {
4367 return;
4368 }
4369 if (present) {
4370 BV_SET(pv->data.v_bv_inventions, id);
4371 } else {
4372 BV_CLR(pv->data.v_bv_inventions, id);
4373 }
4374 gtk_list_store_set(ev->store, &iter, 0, present, -1);
4376 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4377 g_free(buf);
4378 break;
4379
4380 default:
4381 log_error("Unhandled widget toggled signal in "
4382 "extviewer_view_cell_toggled() for objprop id=%d "
4383 "name \"%s\".", propid, objprop_get_name(op));
4384 return;
4385 break;
4386 }
4387
4389}
4390
4391/************************************************************************/
4396{
4397 struct extviewer *ev;
4398 struct objprop *op;
4399 struct property_page *pp;
4401 struct propval value = {{0,}, VALTYPE_STRING, FALSE}, *pv;
4402 GtkTextIter start, end;
4403 char *text;
4404 gchar *buf;
4405
4406 ev = userdata;
4407 if (!ev) {
4408 return;
4409 }
4410
4414
4415 gtk_text_buffer_get_start_iter(textbuf, &start);
4416 gtk_text_buffer_get_end_iter(textbuf, &end);
4417 text = gtk_text_buffer_get_text(textbuf, &start, &end, FALSE);
4418 value.data.v_const_string = text;
4419 pv = &value;
4420
4421 switch (propid) {
4425 gtk_label_set_text(GTK_LABEL(ev->panel_label), buf);
4426 g_free(buf);
4427 break;
4428 default:
4429 log_error("Unhandled widget modified signal in "
4430 "extviewer_textbuf_changed() for objprop id=%d "
4431 "name \"%s\".", propid, objprop_get_name(op));
4432 return;
4433 break;
4434 }
4435
4437 g_free(text);
4438}
4439
4440/************************************************************************/
4444{
4445#define ADDPROP(ARG_id, ARG_name, ARG_tooltip, ARG_flags, ARG_valtype) do { \
4446 struct objprop *MY_op = objprop_new(ARG_id, ARG_name, ARG_tooltip, \
4447 ARG_flags, ARG_valtype, pp); \
4448 objprop_hash_insert(pp->objprop_table, MY_op->id, MY_op); \
4449} while (FALSE)
4450
4451 switch (property_page_get_objtype(pp)) {
4452 case OBJTYPE_TILE:
4453 ADDPROP(OPID_TILE_IMAGE, _("Image"), NULL,
4455 ADDPROP(OPID_TILE_TERRAIN, _("Terrain"), NULL,
4457 ADDPROP(OPID_TILE_RESOURCE, _("Resource"), NULL,
4459 ADDPROP(OPID_TILE_INDEX, _("Index"), NULL,
4461 ADDPROP(OPID_TILE_X, Q_("?coordinate:X"), NULL,
4463 ADDPROP(OPID_TILE_Y, Q_("?coordinate:Y"), NULL,
4465 /* TRANS: The coordinate X in native coordinates.
4466 * The freeciv coordinate system is described in doc/HACKING. */
4467 ADDPROP(OPID_TILE_NAT_X, _("NAT X"), NULL,
4469 /* TRANS: The coordinate Y in native coordinates.
4470 * The freeciv coordinate system is described in doc/HACKING. */
4471 ADDPROP(OPID_TILE_NAT_Y, _("NAT Y"), NULL,
4473 ADDPROP(OPID_TILE_CONTINENT, _("Continent"), NULL,
4475 ADDPROP(OPID_TILE_XY, Q_("?coordinates:X,Y"), NULL,
4477 ADDPROP(OPID_TILE_SPECIALS, _("Specials"), NULL,
4480 ADDPROP(OPID_TILE_ROADS, _("Roads"), NULL,
4483 ADDPROP(OPID_TILE_BASES, _("Bases"), NULL,
4486#ifdef FREECIV_DEBUG
4487 ADDPROP(OPID_TILE_ADDRESS, _("Address"), NULL,
4489#endif /* FREECIV_DEBUG */
4490#if 0
4491 /* Disabled entirely for now as server is not sending other
4492 * players' vision information anyway. */
4493 ADDPROP(OPID_TILE_VISION, _("Vision"), NULL,
4495#endif
4496 /* TRANS: Tile property "Label" label in editor */
4497 ADDPROP(OPID_TILE_LABEL, Q_("?property:Label"), NULL,
4499 return;
4500
4501 case OBJTYPE_STARTPOS:
4502 ADDPROP(OPID_STARTPOS_IMAGE, _("Image"), NULL,
4504 ADDPROP(OPID_STARTPOS_XY, Q_("?coordinates:X,Y"), NULL,
4506 ADDPROP(OPID_STARTPOS_EXCLUDE, _("Exclude Nations"), NULL,
4508 ADDPROP(OPID_STARTPOS_NATIONS, _("Nations"), NULL,
4511 return;
4512
4513 case OBJTYPE_UNIT:
4514 ADDPROP(OPID_UNIT_IMAGE, _("Image"), NULL,
4516#ifdef FREECIV_DEBUG
4517 ADDPROP(OPID_UNIT_ADDRESS, _("Address"), NULL,
4519#endif /* FREECIV_DEBUG */
4520 ADDPROP(OPID_UNIT_TYPE, _("Type"), NULL,
4522 ADDPROP(OPID_UNIT_ID, _("ID"), NULL,
4524 ADDPROP(OPID_UNIT_XY, Q_("?coordinates:X,Y"), NULL,
4526 ADDPROP(OPID_UNIT_MOVES_LEFT, _("Moves Left"), NULL,
4528 ADDPROP(OPID_UNIT_FUEL, _("Fuel"), NULL,
4530 ADDPROP(OPID_UNIT_MOVED, _("Moved"), NULL,
4532 ADDPROP(OPID_UNIT_DONE_MOVING, _("Done Moving"), NULL,
4534 /* TRANS: HP = Hit Points of a unit. */
4535 ADDPROP(OPID_UNIT_HP, _("HP"), NULL,
4537 ADDPROP(OPID_UNIT_VETERAN, _("Veteran"), NULL,
4539 ADDPROP(OPID_UNIT_STAY, _("Stay put"), NULL,
4541 return;
4542
4543 case OBJTYPE_CITY:
4544 ADDPROP(OPID_CITY_IMAGE, _("Image"), NULL,
4546 ADDPROP(OPID_CITY_NAME, _("Name"), NULL,
4548#ifdef FREECIV_DEBUG
4549 ADDPROP(OPID_CITY_ADDRESS, _("Address"), NULL,
4551#endif /* FREECIV_DEBUG */
4552 ADDPROP(OPID_CITY_ID, _("ID"), NULL,
4554 ADDPROP(OPID_CITY_XY, Q_("?coordinates:X,Y"), NULL,
4556 ADDPROP(OPID_CITY_SIZE, _("Size"), NULL,
4558 ADDPROP(OPID_CITY_HISTORY, _("History"), NULL,
4560 ADDPROP(OPID_CITY_BUILDINGS, _("Buildings"), NULL,
4563 ADDPROP(OPID_CITY_FOOD_STOCK, _("Food Stock"), NULL,
4565 ADDPROP(OPID_CITY_SHIELD_STOCK, _("Shield Stock"), NULL,
4567 return;
4568
4569 case OBJTYPE_PLAYER:
4570 ADDPROP(OPID_PLAYER_NAME, _("Name"), NULL,
4573#ifdef FREECIV_DEBUG
4574 ADDPROP(OPID_PLAYER_ADDRESS, _("Address"), NULL,
4576#endif /* FREECIV_DEBUG */
4577 ADDPROP(OPID_PLAYER_NATION, _("Nation"), NULL,
4580 ADDPROP(OPID_PLAYER_GOV, _("Government"), NULL,
4582 VALTYPE_GOV);
4583 ADDPROP(OPID_PLAYER_AGE, _("Age"), NULL,
4585 ADDPROP(OPID_PLAYER_INVENTIONS, _("Inventions"), NULL,
4590 ADDPROP(OPID_PLAYER_SELECT_WEIGHT, _("Select Weight"),
4591 _("How likely user is to get this player by autoselect. '-1' for default behavior."),
4593 VALTYPE_INT);
4594 ADDPROP(OPID_PLAYER_SCIENCE, _("Science"), NULL,
4596 ADDPROP(OPID_PLAYER_GOLD, _("Gold"), NULL,
4598 VALTYPE_INT);
4599 ADDPROP(OPID_PLAYER_INFRAPOINTS, _("Infrapoints"), NULL,
4601 VALTYPE_INT);
4602 return;
4603
4604 case OBJTYPE_GAME:
4605 ADDPROP(OPID_GAME_SCENARIO, _("Scenario"), NULL,
4607 VALTYPE_BOOL);
4609 _("Scenario Name"), NULL,
4613 _("Scenario Authors"), NULL,
4617 _("Scenario Description"), NULL,
4621 _("Save Random Number State"), NULL,
4624 _("Save Players"), NULL,
4627 _("Nation Start Positions"), NULL,
4630 _("Prevent New Cities"), NULL,
4633 _("Saltwater Flooding Lakes"), NULL,
4636 _("Lock to current Ruleset"), NULL,
4638 return;
4639
4640 case NUM_OBJTYPES:
4641 break;
4642 }
4643
4644 log_error("%s(): Unhandled page object type %s (nb %d).", __FUNCTION__,
4647#undef ADDPROP
4648}
4649
4650/************************************************************************/
4673
4674/************************************************************************/
4679 GtkTreeModel *model,
4682 gpointer data)
4683{
4684 struct property_page *pp;
4685 struct objbind *ob = NULL, *old_ob;
4687
4688 pp = data;
4689 if (!pp || !sel_path) {
4690 return TRUE;
4691 }
4692
4693 if (!gtk_tree_model_get_iter(model, &iter, sel_path)) {
4694 return TRUE;
4695 }
4696
4698 gtk_tree_model_get(model, &iter, 0, &ob, -1);
4699 if (currently_selected) {
4700 if (ob == old_ob) {
4701 GList *rows, *p;
4702 GtkTreePath *path;
4703 struct objbind *new_ob = NULL;
4704
4706 for (p = rows; p != NULL; p = p->next) {
4707 path = p->data;
4708 if (gtk_tree_model_get_iter(model, &iter, path)) {
4709 struct objbind *test_ob = NULL;
4710 gtk_tree_model_get(model, &iter, 0, &test_ob, -1);
4711 if (test_ob == ob) {
4712 continue;
4713 }
4714 new_ob = test_ob;
4715 break;
4716 }
4717 }
4720
4722 }
4723 } else {
4725 }
4726
4727 return TRUE;
4728}
4729
4730/************************************************************************/
4765
4766/************************************************************************/
4770static struct property_page *
4772 struct property_editor *pe)
4773{
4774 struct property_page *pp;
4775 GtkWidget *vgrid, *vgrid2, *hgrid, *hgrid2, *paned, *frame, *w;
4776 GtkWidget *scrollwin, *view, *label, *entry, *notebook;
4777 GtkWidget *button, *hsep;
4782 int num_columns = 0;
4784 int col_id = 1;
4785 const char *attr_type_str, *name, *tooltip;
4786 gchar *title;
4787 int grid_row = 0;
4788 int grid2_row = 0;
4789 int grid_col = 0;
4790 int grid2_col = 0;
4791
4792 if (!(objtype < NUM_OBJTYPES)) {
4793 return NULL;
4794 }
4795
4796 pp = fc_calloc(1, sizeof(struct property_page));
4797 pp->objtype = objtype;
4798 pp->pe_parent = pe;
4799
4801
4802 pp->objprop_table = objprop_hash_new();
4804
4805 pp->objbind_table = objbind_hash_new();
4806
4807 pp->tag_table = stored_tag_hash_new();
4808
4811 num_columns++;
4812 }
4814
4815 /* Column zero in the store holds an objbind
4816 * pointer and is never displayed. */
4817 num_columns++;
4820
4825 col_id++;
4826 }
4828
4831
4834 pp->widget = paned;
4835
4836 /* Left side object list view. */
4837
4838 vgrid = gtk_grid_new();
4847
4850 TRUE);
4855
4859
4862 continue;
4863 }
4864
4866 if (!attr_type_str) {
4867 continue;
4868 }
4870 if (col_id < 0) {
4871 continue;
4872 }
4874 if (!name) {
4875 continue;
4876 }
4878 if (!cell) {
4879 continue;
4880 }
4881
4884 NULL);
4885
4889 if (objprop_is_sortable(op)) {
4892 } else {
4894 }
4897
4899
4902 g_signal_connect(sel, "changed",
4906
4908 pp->object_view = view;
4909
4911 hgrid = gtk_grid_new();
4914
4915 button = gtk_button_new();
4916 gtk_button_set_icon_name(GTK_BUTTON(button), "list-add");
4917 gtk_button_set_label(GTK_BUTTON(button), _("Create"));
4920 _("Pressing this button will create a new object of the "
4921 "same type as the current property page and add it to "
4922 "the page. The specific type and count of the objects "
4923 "is taken from the editor tool state. So for example, "
4924 "the \"tool value\" of the unit tool and its \"count\" "
4925 "parameter affect unit creation."));
4926 g_signal_connect(button, "clicked",
4928 gtk_grid_attach(GTK_GRID(hgrid), button, grid_col++, 0, 1, 1);
4929
4930 button = gtk_button_new();
4931 gtk_button_set_icon_name(GTK_BUTTON(button), "list-remove");
4932 gtk_button_set_label(GTK_BUTTON(button), _("Destroy"));
4935 _("Pressing this button will send a request to the server "
4936 "to destroy (i.e. erase) the objects selected in the object "
4937 "list."));
4938 g_signal_connect(button, "clicked",
4940 gtk_grid_attach(GTK_GRID(hgrid), button, grid_col++, 0, 1, 1);
4941 }
4942
4943 /* Right side properties panel. */
4944
4945 hgrid = gtk_grid_new();
4946 grid_col = 0;
4949
4950 vgrid = gtk_grid_new();
4959
4960 /* Extended property viewer to the right of the properties panel.
4961 * This needs to be created before property widgets, since some
4962 * might try to append themselves to this notebook. */
4963
4964 vgrid2 = gtk_grid_new();
4971
4972 notebook = gtk_notebook_new();
4973 gtk_widget_set_vexpand(notebook, TRUE);
4974 gtk_widget_set_size_request(notebook, 256, -1);
4977 gtk_grid_attach(GTK_GRID(vgrid2), notebook, 0, grid2_row++, 1, 1);
4978 pp->extviewer_notebook = notebook;
4979
4982
4983 hgrid2 = gtk_grid_new();
4989
4990 button = gtk_button_new_with_mnemonic(_("_Close"));
4992 g_signal_connect_swapped(button, "clicked",
4993 G_CALLBACK(gtk_window_close), pe->widget);
4994 gtk_grid_attach(GTK_GRID(hgrid2), button, grid2_col++, 0, 1, 1);
4995
4996 /* Now create the properties panel. */
4997
4998 /* TRANS: %s is a type of object that can be edited, such as "Tile",
4999 * "Unit", "Start Position", etc. */
5000 title = g_strdup_printf(_("%s Properties"),
5002 frame = gtk_frame_new(title);
5003 g_free(title);
5004 gtk_widget_set_size_request(frame, 256, -1);
5005 gtk_grid_attach(GTK_GRID(vgrid), frame, 0, grid_row++, 1, 1);
5006
5009 FALSE);
5014
5015 vgrid2 = gtk_grid_new();
5016 grid2_row = 0;
5026
5028 if (!objprop_has_widget(op)) {
5029 continue;
5030 }
5032 if (!w) {
5033 continue;
5034 }
5035 gtk_grid_attach(GTK_GRID(vgrid2), w, 0, grid2_row++, 1, 1);
5037 if (NULL != tooltip) {
5039 }
5041
5042 hgrid2 = gtk_grid_new();
5043 grid2_col = 0;
5048
5049 label = gtk_label_new(_("Filter:"));
5050 gtk_grid_attach(GTK_GRID(hgrid2), label, grid2_col++, 0, 1, 1);
5051
5052 entry = gtk_entry_new();
5054 _("Enter a filter string to limit which properties are shown. "
5055 "The filter is one or more text patterns separated by | "
5056 "(\"or\") or & (\"and\"). The symbol & has higher precedence "
5057 "than |. A pattern may also be negated by prefixing it with !."));
5058 g_signal_connect(entry, "changed",
5061
5062 hgrid2 = gtk_grid_new();
5063 grid2_col = 0;
5066
5067 button = gtk_button_new_with_mnemonic(_("_Refresh"));
5070 _("Pressing this button will reset all modified properties of "
5071 "the selected objects to their current values (the values "
5072 "they have on the server)."));
5073 g_signal_connect(button, "clicked",
5075 gtk_grid_attach(GTK_GRID(hgrid2), button, grid2_col++, 0, 1, 1);
5076
5077 button = gtk_button_new_with_mnemonic(_("_Apply"));
5080 _("Pressing this button will send all modified properties of "
5081 "the objects selected in the object list to the server. "
5082 "Modified properties' names are shown in red in the properties "
5083 "panel."));
5084 g_signal_connect(button, "clicked",
5086 gtk_grid_attach(GTK_GRID(hgrid2), button, grid2_col++, 0, 1, 1);
5087
5088 return pp;
5089}
5090
5091/************************************************************************/
5094static const char *property_page_get_name(const struct property_page *pp)
5095{
5096 if (!pp) {
5097 return "";
5098 }
5100}
5101
5102/************************************************************************/
5105static enum editor_object_type
5107{
5108 if (!pp) {
5109 return -1;
5110 }
5111 return pp->objtype;
5112}
5113
5114/************************************************************************/
5122static GdkPixbuf *create_tile_pixbuf(const struct tile *ptile)
5123{
5125}
5126
5127/************************************************************************/
5138
5139/************************************************************************/
5146static GdkPixbuf *create_city_pixbuf(const struct city *pcity)
5147{
5148 return create_pixbuf_from_layers(city_tile(pcity), NULL, pcity,
5150}
5151
5152/************************************************************************/
5160static GdkPixbuf *create_pixbuf_from_layers(const struct tile *ptile,
5161 const struct unit *punit,
5162 const struct city *pcity,
5163 enum layer_category category)
5164{
5166 int h, fh, fw, canvas_x, canvas_y;
5168 cairo_t *cr;
5169
5173
5175
5178 cairo_paint(cr);
5179 cairo_destroy(cr);
5180
5181 canvas_x = 0;
5182 canvas_y = 0;
5183
5184 canvas_y += (fh - h);
5185
5186 mapview_layer_iterate(layer) {
5187 if (tileset_layer_in_category(layer, category)) {
5188 put_one_element(&canvas, 1.0, layer,
5189 ptile, NULL, NULL, punit, pcity,
5191 }
5195
5196 return pixbuf;
5197}
5198
5199/************************************************************************/
5203{
5204 if (!pp) {
5205 return;
5206 }
5207
5208 gtk_list_store_clear(pp->object_store);
5209 objbind_hash_clear(pp->objbind_table);
5211}
5212
5213/************************************************************************/
5219{
5220 struct objbind *ob;
5222 int id;
5223
5224 if (!pp) {
5225 return;
5226 }
5227
5230 if (id < 0) {
5231 return;
5232 }
5233
5234 if (objbind_hash_lookup(pp->objbind_table, id, NULL)) {
5235 /* Object already exists. */
5236 return;
5237 }
5238
5240 if (!ob) {
5241 return;
5242 }
5243
5245
5246 objbind_hash_insert(pp->objbind_table, ob->object_id, ob);
5247}
5248
5249/************************************************************************/
5254 const struct tile *ptile)
5255{
5256
5257 if (!pp || !ptile) {
5258 return;
5259 }
5260
5261 switch (property_page_get_objtype(pp)) {
5262 case OBJTYPE_TILE:
5264 return;
5265
5266 case OBJTYPE_STARTPOS:
5267 {
5268 struct startpos *psp = map_startpos_get(ptile);
5269
5270 if (NULL != psp) {
5272 }
5273 }
5274 return;
5275
5276 case OBJTYPE_UNIT:
5277 unit_list_iterate(ptile->units, punit) {
5280 return;
5281
5282 case OBJTYPE_CITY:
5283 if (tile_city(ptile)) {
5285 }
5286 return;
5287
5288 case OBJTYPE_PLAYER:
5289 case OBJTYPE_GAME:
5290 return;
5291
5292 case NUM_OBJTYPES:
5293 break;
5294 }
5295
5296 log_error("%s(): Unhandled page object type %s (nb %d).", __FUNCTION__,
5299}
5300
5301/************************************************************************/
5308 struct objprop *op,
5309 struct objbind *ob,
5311{
5312 int col_id;
5313 struct propval *pv;
5314 enum value_types valtype;
5315 char buf[128], *p;
5317 GtkListStore *store;
5318 gchar *buf2;
5319
5320 if (!pp || !pp->object_store || !op || !ob) {
5321 return FALSE;
5322 }
5323
5325 return FALSE;
5326 }
5327
5329 if (col_id < 0) {
5330 return FALSE;
5331 }
5332
5334 if (!pv) {
5335 return FALSE;
5336 }
5337
5339 store = pp->object_store;
5340
5341 switch (valtype) {
5342 case VALTYPE_NONE:
5343 break;
5344 case VALTYPE_INT:
5345 gtk_list_store_set(store, iter, col_id, pv->data.v_int, -1);
5346 break;
5347 case VALTYPE_BOOL:
5348 /* Set as translated string, not as untranslated G_TYPE_BOOLEAN */
5350 break;
5351 case VALTYPE_STRING:
5352 if (fc_strlcpy(buf, pv->data.v_string, 28) >= 28) {
5353 sz_strlcat(buf, "...");
5354 }
5355 for (p = buf; *p; p++) {
5356 if (*p == '\n' || *p == '\t' || *p == '\r') {
5357 *p = ' ';
5358 }
5359 }
5360 gtk_list_store_set(store, iter, col_id, buf, -1);
5361 break;
5362 case VALTYPE_PIXBUF:
5363 gtk_list_store_set(store, iter, col_id, pv->data.v_pixbuf, -1);
5364 break;
5367 case VALTYPE_BV_SPECIAL:
5368 case VALTYPE_BV_ROADS:
5369 case VALTYPE_BV_BASES:
5372 gtk_list_store_set(store, iter, col_id, buf2, -1);
5373 g_free(buf2);
5374 break;
5375 case VALTYPE_NATION:
5376 pixbuf = get_flag(pv->data.v_nation);
5377 gtk_list_store_set(store, iter, col_id, pixbuf, -1);
5378 if (pixbuf) {
5380 }
5381 break;
5382 case VALTYPE_GOV:
5383 if (pv->data.v_gov != NULL) {
5385 } else {
5388 }
5389 gtk_list_store_set(store, iter, col_id, pixbuf, -1);
5390 if (pixbuf) {
5392 }
5393 break;
5395 break;
5396 }
5397
5399
5400 return TRUE;
5401}
5402
5403/************************************************************************/
5408{
5409 struct objbind *focused;
5410
5411 if (!pp || !pp->objbind_table) {
5412 return;
5413 }
5414
5415 if (pp->object_store) {
5418 GtkTreeModel *model;
5419 GtkTreePath *path;
5420
5421 model = GTK_TREE_MODEL(pp->object_store);
5422
5424 if (objbind_get_rowref(ob)) {
5425 continue;
5426 }
5427 gtk_list_store_append(pp->object_store, &iter);
5428 gtk_list_store_set(pp->object_store, &iter, 0, ob, -1);
5429 path = gtk_tree_model_get_path(model, &iter);
5430 rr = gtk_tree_row_reference_new(model, path);
5431 gtk_tree_path_free(path);
5433
5438
5439 if (gtk_tree_model_get_iter_first(model, &iter)) {
5443 }
5444 }
5445
5450}
5451
5452/************************************************************************/
5457{
5458 if (!pp) {
5459 return NULL;
5460 }
5461 return pp->focused_objbind;
5462}
5463
5464/************************************************************************/
5469 struct objbind *ob)
5470{
5471 if (!pp) {
5472 return;
5473 }
5474 pp->focused_objbind = ob;
5475}
5476
5477/************************************************************************/
5482 int object_id)
5483{
5484 struct objbind *ob;
5485
5486 if (!pp || !pp->objbind_table) {
5487 return NULL;
5488 }
5489
5490 objbind_hash_lookup(pp->objbind_table, object_id, &ob);
5491 return ob;
5492}
5493
5494/************************************************************************/
5499 const struct tile_list *tiles)
5500{
5501 if (!pp || !tiles) {
5502 return;
5503 }
5504
5505 tile_list_iterate(tiles, ptile) {
5508
5510}
5511
5512/************************************************************************/
5516{
5517 if (!pp || !pp->objbind_table) {
5518 return 0;
5519 }
5520 return objbind_hash_size(pp->objbind_table);
5521}
5522
5523/************************************************************************/
5528 struct objprop *op,
5529 struct propval *pv)
5530{
5532 GtkTreeModel *model;
5533 GList *rows, *p;
5534 GtkTreePath *path;
5536 struct objbind *ob;
5537 bool changed = FALSE;
5538
5539 if (!pp || !op || !pp->object_view) {
5540 return;
5541 }
5542
5543 if (objprop_is_readonly(op)) {
5544 return;
5545 }
5546
5549
5550 for (p = rows; p != NULL; p = p->next) {
5551 path = p->data;
5552 if (gtk_tree_model_get_iter(model, &iter, path)) {
5553 gtk_tree_model_get(model, &iter, 0, &ob, -1);
5554 changed |= objbind_set_modified_value(ob, op, pv);
5555 }
5556 gtk_tree_path_free(path);
5557 }
5559
5560 if (changed) {
5563 }
5564}
5565
5566/************************************************************************/
5570{
5572 GtkTreeModel *model;
5573 GList *rows, *p;
5574 GtkTreePath *path;
5576 struct objbind *ob;
5577 union packetdata packet;
5578 struct connection *my_conn = &client.conn;
5579
5580 if (!pp || !pp->object_view) {
5581 return;
5582 }
5583
5586 return;
5587 }
5588
5589 packet = property_page_new_packet(pp);
5590 if (!packet.pointers.v_pointer1) {
5591 return;
5592 }
5593
5596 for (p = rows; p != NULL; p = p->next) {
5597 path = p->data;
5598 if (gtk_tree_model_get_iter(model, &iter, path)) {
5599 gtk_tree_model_get(model, &iter, 0, &ob, -1);
5603 if (objprop_is_readonly(op)) {
5604 continue;
5605 }
5609 }
5610 }
5611 gtk_tree_path_free(path);
5612 }
5615
5617}
5618
5619/************************************************************************/
5624{
5625 union packetdata packet;
5626
5627 packet.pointers.v_pointer2 = NULL;
5628
5629 if (!pp) {
5630 packet.pointers.v_pointer1 = NULL;
5631 return packet;
5632 }
5633
5634 switch (property_page_get_objtype(pp)) {
5635 case OBJTYPE_TILE:
5636 packet.tile = fc_calloc(1, sizeof(*packet.tile));
5637 break;
5638 case OBJTYPE_STARTPOS:
5639 packet.startpos = fc_calloc(1, sizeof(*packet.startpos));
5640 break;
5641 case OBJTYPE_UNIT:
5642 packet.unit = fc_calloc(1, sizeof(*packet.unit));
5643 break;
5644 case OBJTYPE_CITY:
5645 packet.city = fc_calloc(1, sizeof(*packet.city));
5646 break;
5647 case OBJTYPE_PLAYER:
5648 packet.player = fc_calloc(1, sizeof(*packet.player));
5649 break;
5650 case OBJTYPE_GAME:
5651 packet.game.game = fc_calloc(1, sizeof(*packet.game.game));
5652 packet.game.desc = fc_calloc(1, sizeof(*packet.game.desc));
5653 break;
5654 case NUM_OBJTYPES:
5655 break;
5656 }
5657
5658 return packet;
5659}
5660
5661/************************************************************************/
5665 union packetdata packet)
5666{
5667 struct connection *my_conn = &client.conn;
5668
5669 if (!pp || !packet.pointers.v_pointer1) {
5670 return;
5671 }
5672
5673 switch (property_page_get_objtype(pp)) {
5674 case OBJTYPE_TILE:
5676 return;
5677 case OBJTYPE_STARTPOS:
5679 return;
5680 case OBJTYPE_UNIT:
5682 return;
5683 case OBJTYPE_CITY:
5685 return;
5686 case OBJTYPE_PLAYER:
5688 return;
5689 case OBJTYPE_GAME:
5690 send_packet_edit_game(my_conn, packet.game.game);
5692 return;
5693 case NUM_OBJTYPES:
5694 break;
5695 }
5696
5697 log_error("%s(): Unhandled object type %s (nb %d).",
5700}
5701
5702/************************************************************************/
5706 union packetdata packet)
5707{
5708 if (!packet.pointers.v_pointer1) {
5709 return;
5710 }
5711
5712 free(packet.pointers.v_pointer1);
5713 packet.pointers.v_pointer1 = NULL;
5714
5715 if (packet.pointers.v_pointer2 != NULL) {
5716 free(packet.pointers.v_pointer2);
5717 packet.pointers.v_pointer2 = NULL;
5718 }
5719}
5720
5721/************************************************************************/
5726{
5728 GtkTreeModel *model;
5730 GtkTreePath *path;
5731 GList *rows, *p;
5732 struct objbind *ob;
5733
5734 if (!pp || !pp->object_view) {
5735 return;
5736 }
5737
5740 return;
5741 }
5742
5744 for (p = rows; p != NULL; p = p->next) {
5745 path = p->data;
5746 if (gtk_tree_model_get_iter(model, &iter, path)) {
5747 gtk_tree_model_get(model, &iter, 0, &ob, -1);
5752 }
5753 gtk_tree_path_free(path);
5754 }
5756
5761}
5762
5763/************************************************************************/
5767{
5769 GtkTreeModel *model;
5771 GtkTreePath *path;
5772 GList *rows, *p;
5773 struct objbind *ob;
5774 struct connection *my_conn = &client.conn;
5775
5776 if (!pp || !pp->object_view) {
5777 return;
5778 }
5779
5782 return;
5783 }
5784
5787 for (p = rows; p != NULL; p = p->next) {
5788 path = p->data;
5789 if (gtk_tree_model_get_iter(model, &iter, path)) {
5790 gtk_tree_model_get(model, &iter, 0, &ob, -1);
5792 }
5793 gtk_tree_path_free(path);
5794 }
5797}
5798
5799/************************************************************************/
5806 struct tile_list *hint_tiles)
5807{
5809 int apno, value, count, size;
5810 int tag;
5811 struct connection *my_conn = &client.conn;
5812 struct tile *ptile = NULL;
5813 struct player *pplayer;
5814
5815 if (!pp) {
5816 return;
5817 }
5818
5821 return;
5822 }
5823
5824 tag = get_next_unique_tag();
5825 count = 1;
5826
5827 switch (objtype) {
5828 case OBJTYPE_STARTPOS:
5829 if (hint_tiles) {
5831 if (NULL == map_startpos_get(atile)) {
5832 ptile = atile;
5833 break;
5834 }
5836 }
5837
5838 if (NULL == ptile) {
5839 ptile = get_center_tile_mapcanvas();
5840 }
5841
5842 if (NULL == ptile) {
5843 break;
5844 }
5845
5847 break;
5848
5849 case OBJTYPE_UNIT:
5850 if (hint_tiles) {
5853 ptile = atile;
5854 break;
5855 }
5857 }
5858
5859 if (!ptile) {
5860 struct unit *punit;
5864 ptile = unit_tile(punit);
5865 break;
5866 }
5868 }
5869
5870 if (!ptile) {
5871 ptile = get_center_tile_mapcanvas();
5872 }
5873
5874 if (!ptile) {
5875 break;
5876 }
5877
5882 value, count, tag);
5883 break;
5884
5885 case OBJTYPE_CITY:
5887 pplayer = player_by_number(apno);
5888 if (pplayer && hint_tiles) {
5890 if (!is_enemy_unit_tile(atile, pplayer)
5892 NULL, FALSE)) {
5893 ptile = atile;
5894 break;
5895 }
5897 }
5898
5899 if (!ptile) {
5900 ptile = get_center_tile_mapcanvas();
5901 }
5902
5903 if (!ptile) {
5904 break;
5905 }
5906
5909 size, tag);
5910 break;
5911
5912 case OBJTYPE_PLAYER:
5914 break;
5915
5916 case OBJTYPE_TILE:
5917 case OBJTYPE_GAME:
5918 case NUM_OBJTYPES:
5919 break;
5920 }
5921
5923}
5924
5925/************************************************************************/
5931 int object_id,
5932 bool removed)
5933{
5934 struct objbind *ob;
5936
5938 if (!ob) {
5939 return;
5940 }
5941
5944 GtkTreePath *path;
5946 GtkTreeModel *model;
5947
5948 model = GTK_TREE_MODEL(pp->object_store);
5950
5951 if (gtk_tree_model_get_iter(model, &iter, path)) {
5952 if (removed) {
5953 gtk_list_store_remove(pp->object_store, &iter);
5954 } else {
5958 }
5959 }
5960
5961 gtk_tree_path_free(path);
5962 }
5963
5964 if (removed) {
5965 objbind_hash_remove(pp->objbind_table, object_id);
5966 return;
5967 }
5968
5973 }
5974}
5975
5976/************************************************************************/
5983 int tag, int object_id)
5984{
5987
5988 if (!property_page_tag_is_known(pp, tag)) {
5989 return;
5990 }
5992
5995
5996 if (!object) {
5997 return;
5998 }
5999
6002}
6003
6004/************************************************************************/
6009 struct extviewer *ev)
6010{
6011 GtkWidget *w;
6012
6013 if (!pp || !ev) {
6014 return;
6015 }
6016
6018 if (!w) {
6019 return;
6020 }
6021 gtk_notebook_append_page(GTK_NOTEBOOK(pp->extviewer_notebook), w, NULL);
6022}
6023
6024/************************************************************************/
6029 struct extviewer *ev)
6030{
6031 GtkWidget *w;
6032 GtkNotebook *notebook;
6033 int page;
6034
6035 if (!pp || !ev) {
6036 return;
6037 }
6038
6040 if (!w) {
6041 return;
6042 }
6043
6044 notebook = GTK_NOTEBOOK(pp->extviewer_notebook);
6045 page = gtk_notebook_page_num(notebook, w);
6046 gtk_notebook_set_current_page(notebook, page);
6047}
6048
6049/************************************************************************/
6054 int tag, int count)
6055{
6056 if (!pp || !pp->tag_table) {
6057 return;
6058 }
6059
6060 if (stored_tag_hash_lookup(pp->tag_table, tag, NULL)) {
6061 log_error("Attempted to insert object creation tag %d "
6062 "twice into tag table for property page %p (%d %s).",
6065 return;
6066 }
6067
6068 stored_tag_hash_insert(pp->tag_table, tag, count);
6069}
6070
6071/************************************************************************/
6076 int tag)
6077{
6078 int count;
6079
6080 if (!pp || !pp->tag_table) {
6081 return;
6082 }
6083
6084 if (stored_tag_hash_lookup(pp->tag_table, tag, &count)) {
6085 if (0 >= --count) {
6086 stored_tag_hash_remove(pp->tag_table, tag);
6087 }
6088 }
6089}
6090
6091/************************************************************************/
6094static bool property_page_tag_is_known(struct property_page *pp, int tag)
6095{
6096 if (!pp || !pp->tag_table) {
6097 return FALSE;
6098 }
6099 return stored_tag_hash_lookup(pp->tag_table, tag, NULL);
6100}
6101
6102/************************************************************************/
6106{
6107 if (!pp || !pp->tag_table) {
6108 return;
6109 }
6110 stored_tag_hash_clear(pp->tag_table);
6111}
6112
6113/************************************************************************/
6122
6123/************************************************************************/
6133
6134/************************************************************************/
6139{
6140 struct property_page *pp = userdata, *tile_pp;
6141 struct tile_list *tiles = NULL;
6142 struct tile *ptile;
6143
6144 if (!pp) {
6145 return;
6146 }
6147
6149 tiles = tile_list_new();
6150
6152 ptile = objbind_get_object(ob);
6153 if (ptile) {
6154 tile_list_append(tiles, ptile);
6155 }
6157
6159 tile_list_destroy(tiles);
6160}
6161
6162/************************************************************************/
6171
6172/************************************************************************/
6178{
6179 struct property_page *pp;
6180 GtkWidget *label;
6181 const char *name;
6182
6183 if (!pe || !pe->notebook) {
6184 return FALSE;
6185 }
6186
6187 if (!(objtype < NUM_OBJTYPES)) {
6188 return FALSE;
6189 }
6190
6192 if (!pp) {
6193 return FALSE;
6194 }
6195
6197 label = gtk_label_new(name);
6199 pp->widget, label);
6200
6201 pe->property_pages[objtype] = pp;
6202
6203 return TRUE;
6204}
6205
6206/************************************************************************/
6209static struct property_page *
6212{
6213 if (!pe || !(objtype < NUM_OBJTYPES)) {
6214 return NULL;
6215 }
6216
6217 return pe->property_pages[objtype];
6218}
6219
6220/************************************************************************/
6224{
6225 struct property_editor *pe;
6226 GtkWidget *win, *notebook, *vgrid;
6228 int grid_row = 0;
6229
6230 pe = fc_calloc(1, sizeof(*pe));
6231
6232 /* The property editor dialog window. */
6233
6234 win = gtk_window_new();
6235 gtk_window_set_title(GTK_WINDOW(win), _("Property Editor"));
6245 pe->widget = win;
6246
6247 vgrid = gtk_grid_new();
6249
6250 /* Property pages. */
6251
6255 pe->notebook = notebook;
6256
6257 for (objtype = 0; objtype < NUM_OBJTYPES; objtype++) {
6259 }
6260
6261 return pe;
6262}
6263
6264/************************************************************************/
6274
6275/************************************************************************/
6279 const struct tile_list *tiles)
6280{
6281 struct property_page *pp;
6283 int i;
6284 const enum editor_object_type preferred[] = {
6289 };
6290
6291 if (!pe || !tiles) {
6292 return;
6293 }
6294
6295 for (objtype = 0; objtype < NUM_OBJTYPES; objtype++) {
6298 }
6299
6300 for (i = 0; i < ARRAY_SIZE(preferred) - 1; i++) {
6303 break;
6304 }
6305 }
6306 objtype = preferred[i];
6308}
6309
6310/************************************************************************/
6316{
6317 if (pe == NULL || pe->widget == NULL) {
6318 return;
6319 }
6320
6321 gtk_widget_set_visible(pe->widget, TRUE);
6322
6324 if (objtype < NUM_OBJTYPES) {
6326 }
6327}
6328
6329/************************************************************************/
6333{
6334 if (pe == NULL || pe->widget == NULL) {
6335 return;
6336 }
6337
6339}
6340
6341/************************************************************************/
6347 int object_id,
6348 bool remove)
6349{
6350 struct property_page *pp;
6351
6352 if (!pe) {
6353 return;
6354 }
6355
6356 if (!(objtype < NUM_OBJTYPES)) {
6357 return;
6358 }
6359
6362}
6363
6364/************************************************************************/
6368 int tag, int object_id)
6369{
6371 struct property_page *pp;
6372
6373 for (objtype = 0; objtype < NUM_OBJTYPES; objtype++) {
6375 continue;
6376 }
6378 property_page_object_created(pp, tag, object_id);
6379 }
6380}
6381
6382/************************************************************************/
6386{
6388 struct property_page *pp;
6389
6390 if (!pe) {
6391 return;
6392 }
6393
6394 for (objtype = 0; objtype < NUM_OBJTYPES; objtype++) {
6398 }
6399}
6400
6401/************************************************************************/
6407{
6408 struct property_page *pp;
6409
6410 if (!pe) {
6411 return;
6412 }
6413
6415 if (!pp) {
6416 return;
6417 }
6418
6420
6421 switch (objtype) {
6422 case OBJTYPE_PLAYER:
6423 players_iterate(pplayer) {
6424 property_page_add_objbind(pp, pplayer);
6426 break;
6427 case OBJTYPE_GAME:
6429 break;
6430 case OBJTYPE_TILE:
6431 case OBJTYPE_STARTPOS:
6432 case OBJTYPE_UNIT:
6433 case OBJTYPE_CITY:
6434 case NUM_OBJTYPES:
6435 break;
6436 }
6437
6440}
6441
6442/************************************************************************/
6453static struct property_filter *property_filter_new(const char *filter)
6454{
6455 struct property_filter *pf;
6456 struct pf_conjunction *pfc;
6457 struct pf_pattern *pfp;
6460 const char *pattern;
6461 int i, j;
6462
6463 pf = fc_calloc(1, sizeof(*pf));
6464
6465 if (!filter || filter[0] == '\0') {
6466 return pf;
6467 }
6468
6472
6473 for (i = 0; i < or_clause_count; i++) {
6474 if (or_clauses[i][0] == '\0') {
6475 continue;
6476 }
6477 pfc = &pf->disjunction[pf->count];
6478
6482
6483 for (j = 0; j < and_clause_count; j++) {
6484 if (and_clauses[j][0] == '\0') {
6485 continue;
6486 }
6487 pfp = &pfc->conjunction[pfc->count];
6488 pattern = and_clauses[j];
6489
6490 switch (pattern[0]) {
6491 case '!':
6492 pfp->negate = TRUE;
6493 pfp->text = fc_strdup(pattern + 1);
6494 break;
6495 default:
6496 pfp->text = fc_strdup(pattern);
6497 break;
6498 }
6499 pfc->count++;
6500 }
6502 pf->count++;
6503 }
6504
6506
6507 return pf;
6508}
6509
6510/************************************************************************/
6528 const struct objprop *op)
6529{
6530 struct pf_pattern *pfp;
6531 struct pf_conjunction *pfc;
6532 const char *name;
6533 bool match, or_result, and_result;
6534 int i, j;
6535
6536 if (!pf) {
6537 return TRUE;
6538 }
6539 if (!op) {
6540 return FALSE;
6541 }
6542
6544 if (!name) {
6545 return FALSE;
6546 }
6547
6548 if (pf->count < 1) {
6549 return TRUE;
6550 }
6551
6552 or_result = FALSE;
6553
6554 for (i = 0; i < pf->count; i++) {
6555 pfc = &pf->disjunction[i];
6556 and_result = TRUE;
6557 for (j = 0; j < pfc->count; j++) {
6558 pfp = &pfc->conjunction[j];
6559 match = (pfp->text[0] == '\0'
6560 || fc_strcasestr(name, pfp->text));
6561 if (pfp->negate) {
6562 match = !match;
6563 }
6564 and_result = and_result && match;
6565 if (!and_result) {
6566 break;
6567 }
6568 }
6570 if (or_result) {
6571 break;
6572 }
6573 }
6574
6575 return or_result;
6576}
6577
6578/************************************************************************/
6582{
6583 struct pf_pattern *pfp;
6584 struct pf_conjunction *pfc;
6585 int i, j;
6586
6587 if (!pf) {
6588 return;
6589 }
6590
6591 for (i = 0; i < pf->count; i++) {
6592 pfc = &pf->disjunction[i];
6593 for (j = 0; j < pfc->count; j++) {
6594 pfp = &pfc->conjunction[j];
6595 if (pfp->text != NULL) {
6596 free(pfp->text);
6597 pfp->text = NULL;
6598 }
6599 }
6600 pfc->count = 0;
6601 }
6602 pf->count = 0;
6603 free(pf);
6604}
6605
6606/************************************************************************/
6610{
6611 switch (vl) {
6612 case V_MAIN:
6613 /* TRANS: Vision layer name. Feel free to leave untranslated. */
6614 return _("Seen (Main)");
6615 case V_INVIS:
6616 /* TRANS: Vision layer name. Feel free to leave untranslated. */
6617 return _("Seen (Invis)");
6618 case V_SUBSURFACE:
6619 /* TRANS: Vision layer name. Feel free to leave untranslated. */
6620 return _("Seen (Subsurface)");
6621 case V_COUNT:
6622 break;
6623 }
6624
6625 log_error("%s(): Unrecognized vision layer %d.", __FUNCTION__, vl);
6626 return _("Unknown");
6627}
Base_type_id base_number(const struct base_type *pbase)
Definition base.c:92
Base_type_id base_count(void)
Definition base.c:109
bool dbv_isset(const struct dbv *pdbv, int bit)
Definition bitvector.c:120
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
#define BV_SET(bv, bit)
Definition bitvector.h:81
#define BV_ARE_EQUAL(vec1, vec2)
Definition bitvector.h:113
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
#define BV_CLR(bv, bit)
Definition bitvector.h:86
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:2132
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:1487
#define city_tile(_pcity_)
Definition city.h:564
static citizens city_size_get(const struct city *pcity)
Definition city.h:569
#define city_owner(_pcity_)
Definition city.h:563
#define MAX_CITY_SIZE
Definition city.h:106
#define I_DESTROYED
Definition city.h:248
#define I_NEVER
Definition city.h:247
struct civclient client
bool client_nation_is_in_current_set(const struct nation_type *pnation)
Definition climisc.c:1508
char * incite_cost
Definition comments.c:75
void connection_do_buffer(struct connection *pc)
Definition connection.c:324
void connection_do_unbuffer(struct connection *pc)
Definition connection.c:336
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
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:1114
#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:143
Government_type_id government_count(void)
Definition government.c:71
struct government * government_by_number(const Government_type_id gov)
Definition government.c:103
Government_type_id government_index(const struct government *pgovern)
Definition government.c:82
#define governments_iterate(NAME_pgov)
Definition government.h:124
#define governments_iterate_end
Definition government.h:127
#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:5704
static void property_page_send_values(struct property_page *pp)
Definition editprop.c:5548
static void objprop_setup_widget(struct objprop *op)
Definition editprop.c:2953
static void property_page_store_creation_tag(struct property_page *pp, int tag, int count)
Definition editprop.c:6031
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:3465
static const char * objprop_get_name(const struct objprop *op)
Definition editprop.c:2833
const char * vision_layer_get_name(enum vision_layer)
Definition editprop.c:6585
static int objbind_get_object_id(struct objbind *ob)
Definition editprop.c:1381
static void objprop_set_extviewer(struct objprop *op, struct extviewer *ev)
Definition editprop.c:3442
static GtkWidget * extviewer_get_panel_widget(struct extviewer *ev)
Definition editprop.c:3797
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:6321
static struct propstate * propstate_new(struct objprop *op, struct propval *pv)
Definition editprop.c:1265
static const char * valtype_get_name(enum value_types valtype)
Definition editprop.c:779
static void propstate_destroy(struct propstate *ps)
Definition editprop.c:1297
static bool objbind_set_modified_value(struct objbind *ob, struct objprop *op, struct propval *pv)
Definition editprop.c:2129
static GtkCellRenderer * objprop_create_cell_renderer(const struct objprop *op)
Definition editprop.c:2857
static void extviewer_clear_widgets(struct extviewer *ev)
Definition editprop.c:4090
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:3382
static bool property_editor_add_page(struct property_editor *pe, enum editor_object_type objtype)
Definition editprop.c:6154
static void propstate_clear_value(struct propstate *ps)
Definition editprop.c:1284
static void objbind_pack_modified_value(struct objbind *ob, struct objprop *op, union packetdata packet)
Definition editprop.c:2381
static struct objbind * property_page_get_focused_objbind(struct property_page *pp)
Definition editprop.c:5435
static bool objprop_has_widget(const struct objprop *op)
Definition editprop.c:2746
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:2213
static struct extviewer * objprop_get_extviewer(struct objprop *op)
Definition editprop.c:3454
static void extviewer_refresh_widgets(struct extviewer *ev, struct propval *pv)
Definition editprop.c:3820
static enum editor_object_type property_page_get_objtype(const struct property_page *pp)
Definition editprop.c:5085
#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:6006
static gpointer objbind_get_object(struct objbind *ob)
Definition editprop.c:1365
static const char * property_page_get_name(const struct property_page *pp)
Definition editprop.c:5073
void property_editor_handle_object_created(struct property_editor *pe, int tag, int object_id)
Definition editprop.c:6343
static bool objbind_property_is_modified(struct objbind *ob, struct objprop *op)
Definition editprop.c:2084
static struct propval * propstate_get_value(struct propstate *ps)
Definition editprop.c:1327
static void property_page_clear_tags(struct property_page *pp)
Definition editprop.c:6083
static void property_page_object_created(struct property_page *pp, int tag, int object_id)
Definition editprop.c:5960
static bool property_page_tag_is_known(struct property_page *pp, int tag)
Definition editprop.c:6072
static void property_page_remove_creation_tag(struct property_page *pp, int tag)
Definition editprop.c:6053
static void property_page_load_tiles(struct property_page *pp, const struct tile_list *tiles)
Definition editprop.c:5477
static void property_page_create_objects(struct property_page *pp, struct tile_list *hint_tiles)
Definition editprop.c:5784
static void property_page_add_extviewer(struct property_page *pp, struct extviewer *ev)
Definition editprop.c:5986
static void property_page_refresh_button_clicked(GtkButton *button, gpointer userdata)
Definition editprop.c:6105
static void property_page_set_focused_objbind(struct property_page *pp, struct objbind *ob)
Definition editprop.c:5447
static void property_page_setup_objprops(struct property_page *pp)
Definition editprop.c:4435
static void objbind_set_rowref(struct objbind *ob, GtkTreeRowReference *rr)
Definition editprop.c:2653
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:2070
static struct propval * objbind_get_value_from_object(struct objbind *ob, struct objprop *op)
Definition editprop.c:1442
static void propval_free(struct propval *pv)
Definition editprop.c:1127
static struct property_filter * property_filter_new(const char *filter)
Definition editprop.c:6429
static bool property_page_set_store_value(struct property_page *pp, struct objprop *op, struct objbind *ob, GtkTreeIter *iter)
Definition editprop.c:5286
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:2115
static bool property_filter_match(struct property_filter *pf, const struct objprop *op)
Definition editprop.c:6503
void property_editor_popup(struct property_editor *pe, enum editor_object_type objtype)
Definition editprop.c:6291
static void property_page_destroy_button_clicked(GtkButton *button, gpointer userdata)
Definition editprop.c:6143
static struct objbind * objbind_new(enum editor_object_type objtype, gpointer object)
Definition editprop.c:1339
static gboolean property_page_selection_func(GtkTreeSelection *sel, GtkTreeModel *model, GtkTreePath *path, gboolean currently_selected, gpointer data)
Definition editprop.c:4670
static int property_page_get_num_objbinds(const struct property_page *pp)
Definition editprop.c:5494
static bool objprop_show_in_listview(const struct objprop *op)
Definition editprop.c:2735
static GType objprop_get_gtype(const struct objprop *op)
Definition editprop.c:2691
static void objprop_set_treeview_column(struct objprop *op, GtkTreeViewColumn *col)
Definition editprop.c:2809
static void objbind_pack_current_values(struct objbind *ob, union packetdata packet)
Definition editprop.c:2238
static const char * objprop_get_attribute_type_string(const struct objprop *op)
Definition editprop.c:2760
static struct propval * propval_copy(struct propval *pv)
Definition editprop.c:1045
struct property_editor * editprop_get_property_editor(void)
Definition editprop.c:6244
void property_editor_reload(struct property_editor *pe, enum editor_object_type objtype)
Definition editprop.c:6381
static GdkPixbuf * create_unit_pixbuf(const struct unit *punit)
Definition editprop.c:5113
static void extviewer_view_cell_toggled(GtkCellRendererToggle *cell, gchar *path, gpointer userdata)
Definition editprop.c:4165
static struct property_editor * property_editor_new(void)
Definition editprop.c:6201
static void property_page_send_packet(struct property_page *pp, union packetdata packet)
Definition editprop.c:5643
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:2676
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:2724
static int get_next_unique_tag(void)
Definition editprop.c:1034
static bool objprop_is_sortable(const struct objprop *op)
Definition editprop.c:2878
static void property_page_add_objbinds_from_tile(struct property_page *pp, const struct tile *ptile)
Definition editprop.c:5232
static const char * objprop_get_tooltip(const struct objprop *op)
Definition editprop.c:2844
static GtkTreeRowReference * objbind_get_rowref(struct objbind *ob)
Definition editprop.c:2665
static void property_filter_free(struct property_filter *pf)
Definition editprop.c:6557
static void objprop_widget_spin_button_changed(GtkSpinButton *spin, gpointer userdata)
Definition editprop.c:2919
#define PF_DISJUNCTION_SEPARATOR
Definition editprop.c:119
static GtkWidget * objprop_get_child_widget(struct objprop *op, const char *widget_name)
Definition editprop.c:3409
static void property_page_selection_changed(GtkTreeSelection *sel, gpointer userdata)
Definition editprop.c:4645
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:3501
static bool propval_equal(struct propval *pva, struct propval *pvb)
Definition editprop.c:1178
static void property_page_quick_find_entry_changed(GtkWidget *entry, gpointer userdata)
Definition editprop.c:4725
static void objprop_refresh_widget(struct objprop *op, struct objbind *ob)
Definition editprop.c:3131
#define PF_MAX_CLAUSES
Definition editprop.c:118
void property_editor_popdown(struct property_editor *pe)
Definition editprop.c:6309
static void objbind_destroy(struct objbind *ob)
Definition editprop.c:2194
static void property_page_add_objbind(struct property_page *pp, gpointer object_data)
Definition editprop.c:5196
static void objbind_request_destroy_object(struct objbind *ob)
Definition editprop.c:1394
static void property_page_create_button_clicked(GtkButton *button, gpointer userdata)
Definition editprop.c:6115
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:5139
static union packetdata property_page_new_packet(struct property_page *pp)
Definition editprop.c:5602
static void propstate_set_value(struct propstate *ps, struct propval *pv)
Definition editprop.c:1312
static int objprop_get_column_id(const struct objprop *op)
Definition editprop.c:2798
static GdkPixbuf * create_tile_pixbuf(const struct tile *ptile)
Definition editprop.c:5101
static struct objprop * extviewer_get_objprop(struct extviewer *ev)
Definition editprop.c:3785
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:5460
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:1883
static void property_page_free_packet(struct property_page *pp, union packetdata packet)
Definition editprop.c:5684
static GdkPixbuf * create_city_pixbuf(const struct city *pcity)
Definition editprop.c:5125
#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:4145
static void property_page_destroy_objects(struct property_page *pp)
Definition editprop.c:5745
void property_editor_load_tiles(struct property_editor *pe, const struct tile_list *tiles)
Definition editprop.c:6255
static struct property_page * property_page_new(enum editor_object_type objtype, struct property_editor *parent)
Definition editprop.c:4767
#define property_page_objprop_iterate_end
Definition editprop.c:637
static void property_page_clear_objbinds(struct property_page *pp)
Definition editprop.c:5181
void property_editor_clear(struct property_editor *pe)
Definition editprop.c:6361
#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:2785
static void objbind_bind_properties(struct objbind *ob, struct property_page *pp)
Definition editprop.c:2224
static void property_page_fill_widgets(struct property_page *pp)
Definition editprop.c:5386
static bool objbind_has_modified_properties(struct objbind *ob)
Definition editprop.c:2103
static void property_page_change_value(struct property_page *pp, struct objprop *op, struct propval *pv)
Definition editprop.c:5506
static void objprop_widget_toggle_button_changed(GtkToggleButton *button, gpointer userdata)
Definition editprop.c:2936
#define PF_CONJUNCTION_SEPARATOR
Definition editprop.c:120
static void property_page_apply_button_clicked(GtkButton *button, gpointer userdata)
Definition editprop.c:6094
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:3476
static GtkWidget * extviewer_get_view_widget(struct extviewer *ev)
Definition editprop.c:3809
static GtkWidget * objprop_get_widget(struct objprop *op)
Definition editprop.c:3367
static void propval_free_data(struct propval *pv)
Definition editprop.c:1141
static void extviewer_textbuf_changed(GtkTextBuffer *textbuf, gpointer userdata)
Definition editprop.c:4386
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:5908
static bool objprop_is_readonly(const struct objprop *op)
Definition editprop.c:2892
#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:2822
static struct property_page * property_editor_get_page(struct property_editor *pe, enum editor_object_type objtype)
Definition editprop.c:6188
static struct propval * objbind_get_modified_value(struct objbind *ob, struct objprop *op)
Definition editprop.c:2175
GtkWidget * toplevel
Definition gui_main.c:125
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:2903
#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:194
#define log_error(message,...)
Definition log.h:103
struct startpos * map_startpos_get(const struct tile *ptile)
Definition map.c:1883
int startpos_number(const struct startpos *psp)
Definition map.c:1633
#define nat_x
#define nat_y
struct tile * startpos_tile(const struct startpos *psp)
Definition map.c:1676
const struct nation_hash * startpos_raw_nations(const struct startpos *psp)
Definition map.c:1765
bool startpos_pack(const struct startpos *psp, struct packet_edit_startpos_full *packet)
Definition map.c:1706
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:456
bool startpos_is_excluding(const struct startpos *psp)
Definition map.c:1753
struct startpos * map_startpos_by_number(int id)
Definition map.c:1624
#define index_to_native_pos(pnat_x, pnat_y, mindex)
Definition map.h:157
#define index_to_map_pos(pmap_x, pmap_y, mindex)
Definition map.h:233
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:319
#define MAX_MOVE_FRAGS
Definition movement.h:29
Nation_type_id nation_count(void)
Definition nation.c:507
Nation_type_id nation_number(const struct nation_type *pnation)
Definition nation.c:486
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:475
struct nation_type * nation_of_player(const struct player *pplayer)
Definition nation.c:444
bool is_nation_playable(const struct nation_type *nation)
Definition nation.c:200
Nation_type_id nation_index(const struct nation_type *pnation)
Definition nation.c:498
enum barbarian_type nation_barbarian_type(const struct nation_type *nation)
Definition nation.c:211
#define nation_hash_iterate(nationhash, pnation)
Definition nation.h:93
#define nations_iterate_end
Definition nation.h:336
#define nations_iterate(NAME_pnation)
Definition nation.h:333
#define nation_hash_iterate_end
Definition nation.h:95
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)
bool player_slot_is_used(const struct player_slot *pslot)
Definition player.c:448
struct player * player_by_number(const int player_id)
Definition player.c:849
int player_number(const struct player *pplayer)
Definition player.c:837
const char * player_name(const struct player *pplayer)
Definition player.c:895
int player_slot_index(const struct player_slot *pslot)
Definition player.c:426
bool player_has_flag(const struct player *pplayer, enum plr_flag_id flag)
Definition player.c:1990
int player_index(const struct player *pplayer)
Definition player.c:829
bool pplayers_allied(const struct player *pplayer, const struct player *pplayer2)
Definition player.c:1405
struct player * player_slot_get_player(const struct player_slot *pslot)
Definition player.c:437
#define players_iterate_end
Definition player.h:537
#define players_iterate(_pplayer)
Definition player.h:532
#define player_slots_iterate(_pslot)
Definition player.h:523
#define player_slots_iterate_end
Definition player.h:527
struct research * research_get(const struct player *pplayer)
Definition research.c:128
enum tech_state research_invention_state(const struct research *presearch, Tech_type_id tech)
Definition research.c:619
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
int turn
Definition city.h:246
cairo_surface_t * surface
Definition canvas.h:23
Definition city.h:320
int food_stock
Definition city.h:367
struct built_status built[B_LAST]
Definition city.h:394
int history
Definition city.h:410
int id
Definition city.h:326
char * name
Definition city.h:321
int shield_stock
Definition city.h:368
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
int built[B_LAST]
char name[MAX_LEN_CITYNAME]
char scenario_name[256]
char scenario_authors[MAX_LEN_PACKET/3]
Nation_type_id nation
char name[MAX_LEN_NAME]
Government_type_id government
bool inventions[A_LAST+1]
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:65
int autoselect_weight
Definition player.h:297
struct government * government
Definition player.h:256
int turns_alive
Definition player.h:264
struct player_economic economic
Definition player.h:282
char name[MAX_LEN_NAME]
Definition player.h:249
struct nation_type * nation
Definition player.h:258
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:41
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:65
Continent_id continent
Definition tile.h:54
Definition unit.h:138
int moves_left
Definition unit.h:150
int id
Definition unit.h:145
bool moved
Definition unit.h:173
int hp
Definition unit.h:151
int fuel
Definition unit.h:153
bool stay
Definition unit.h:205
bool done_moving
Definition unit.h:181
int veteran
Definition unit.h:152
struct civ_map map
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:974
size_t fc_strlcpy(char *dest, const char *src, size_t n)
Definition support.c:791
char * fc_strcasestr(const char *haystack, const char *needle)
Definition support.c:440
#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:290
Tech_type_id advance_index(const struct advance *padvance)
Definition tech.c:89
#define advance_index_iterate_end
Definition tech.h:248
static Tech_type_id advance_count(void)
Definition tech.h:170
#define A_FIRST
Definition tech.h:44
#define advance_iterate(_p)
Definition tech.h:275
#define advance_iterate_end
Definition tech.h:276
#define advance_index_iterate(_start, _index)
Definition tech.h:244
const char * terrain_name_translation(const struct terrain *pterrain)
Definition terrain.c:238
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_index(_pt_)
Definition tile.h:88
#define tile_resource(_tile)
Definition tile.h:102
#define tile_list_iterate(tile_list, ptile)
Definition tile.h:73
#define tile_terrain(_tile)
Definition tile.h:110
#define TILE_XY(ptile)
Definition tile.h:43
#define tile_list_iterate_end
Definition tile.h:75
static const bv_extras * tile_extras(const struct tile *ptile)
Definition tile.h:120
#define tile_has_extra(ptile, pextra)
Definition tile.h:147
struct sprite * get_government_sprite(const struct tileset *t, const struct government *gov)
Definition tilespec.c:6793
int tileset_small_sprite_width(const struct tileset *t)
Definition tilespec.c:901
int tileset_full_tile_height(const struct tileset *t)
Definition tilespec.c:789
bool tileset_layer_in_category(enum mapview_layer layer, enum layer_category cat)
Definition tilespec.c:7328
int tileset_small_sprite_height(const struct tileset *t)
Definition tilespec.c:937
int tileset_tile_height(const struct tileset *t)
Definition tilespec.c:765
int tileset_full_tile_width(const struct tileset *t)
Definition tilespec.c:776
int tileset_tile_width(const struct tileset *t)
Definition tilespec.c:753
#define mapview_layer_iterate(layer)
Definition tilespec.h:175
#define mapview_layer_iterate_end
Definition tilespec.h:183
layer_category
Definition tilespec.h:189
@ LAYER_CATEGORY_TILE
Definition tilespec.h:191
@ LAYER_CATEGORY_CITY
Definition tilespec.h:190
@ LAYER_CATEGORY_UNIT
Definition tilespec.h:192
gpointer v_pointer2
Definition editprop.c:99
struct packet_edit_tile * tile
Definition editprop.c:101
gpointer v_pointer1
Definition editprop.c:98
struct packetdata::@148 pointers
struct packet_edit_unit * unit
Definition editprop.c:104
struct packet_edit_player * player
Definition editprop.c:105
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:397
static bool is_enemy_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:420
#define unit_owner(_pu)
Definition unit.h:396
static bool is_non_allied_unit_tile(const struct tile *ptile, const struct player *pplayer)
Definition unit.h:432
#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:123
int utype_veteran_levels(const struct unit_type *punittype)
Definition unittype.c:2625
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1560
#define utype_fuel(ptype)
Definition unittype.h:839
#define vision_layer_iterate(v)
Definition vision.h:77
#define vision_layer_iterate_end
Definition vision.h:80