rnd-20060511-1-src
[rocksndiamonds.git] / src / files.c
index 9d145f6380c31220c5abdebde613710e36aecf73..44d0dbbfe08b4e71e4ab870d761022d512d5c24f 100644 (file)
@@ -154,10 +154,10 @@ static void LoadLevel_InitPlayfield(struct LevelInfo *, char *);
 
 /* temporary variables used to store pointers to structure members */
 static struct LevelInfo li;
-static struct ElementInfo xx_ei;
+static struct ElementInfo xx_ei, yy_ei;
 static struct ElementChangeInfo xx_change;
 static struct ElementGroupInfo xx_group;
-static unsigned int xx_event_bits_0_31, xx_event_bits_32_63;
+static unsigned int xx_event_bits[NUM_CE_BITFIELDS];
 static char xx_default_description[MAX_ELEMENT_NAME_LEN + 1];
 static int xx_default_description_length;
 static int xx_num_contents;
@@ -174,6 +174,7 @@ struct ElementFileConfig
   int default_value;           /* initial default value for this variable */
 
   /* (optional) */
+  void *value_copy;            /* variable that holds the data to be copied */
   void *num_entities;          /* number of entities for multi-byte data */
   int default_num_entities;    /* default number of entities for this data */
   int max_num_entities;                /* maximal number of entities for this data */
@@ -463,13 +464,13 @@ static struct ElementFileConfig element_conf[] =
   {
     EL_EMC_ANDROID,
     TYPE_ELEMENT_LIST,                 CONF_VALUE_BYTES(1),
-    &li.android_clone_element[0],      EL_EMPTY,
+    &li.android_clone_element[0],      EL_EMPTY, NULL,
     &li.num_android_clone_elements,    1, MAX_ANDROID_ELEMENTS
   },
   {
     EL_EMC_MAGIC_BALL,
     TYPE_CONTENT_LIST,                 CONF_VALUE_BYTES(2),
-    &li.ball_content,                  EL_EMPTY,
+    &li.ball_content,                  EL_EMPTY, NULL,
     &li.num_ball_contents,             4, MAX_ELEMENT_CONTENTS
   },
 
@@ -486,6 +487,7 @@ static struct ElementFileConfig custom_element_conf[] =
     -1,
     TYPE_STRING,                       CONF_VALUE_BYTES(1),
     &xx_ei.description[0],             -1,
+    &yy_ei.description[0],
     &xx_default_description_length,    -1, MAX_ELEMENT_NAME_LEN,
     &xx_default_description[0]
   },
@@ -493,155 +495,177 @@ static struct ElementFileConfig custom_element_conf[] =
   {
     -1,
     TYPE_BITFIELD,                     CONF_VALUE_32_BIT(1),
-    &xx_ei.properties[EP_BITFIELD_BASE],
-#if 0
-    EP_BITMASK_DEFAULT
-#else
-    (1 << EP_CAN_MOVE_INTO_ACID)
-#endif
+    &xx_ei.properties[EP_BITFIELD_BASE_NR], EP_BITMASK_BASE_DEFAULT,
+    &yy_ei.properties[EP_BITFIELD_BASE_NR]
   },
 #if 0
   /* (reserved) */
   {
     -1,
     TYPE_BITFIELD,                     CONF_VALUE_32_BIT(2),
-    &xx_ei.properties[EP_BITFIELD_BASE + 1], EP_BITMASK_DEFAULT
+    &xx_ei.properties[EP_BITFIELD_BASE_NR + 1], EP_BITMASK_DEFAULT,
+    &yy_ei.properties[EP_BITFIELD_BASE_NR + 1]
   },
 #endif
 
   {
     -1,
     TYPE_BOOLEAN,                      CONF_VALUE_8_BIT(1),
-    &xx_ei.use_gfx_element,            FALSE
+    &xx_ei.use_gfx_element,            FALSE,
+    &yy_ei.use_gfx_element
   },
   {
     -1,
     TYPE_ELEMENT,                      CONF_VALUE_16_BIT(1),
-    &xx_ei.gfx_element,                        EL_EMPTY_SPACE
+    &xx_ei.gfx_element,                        EL_EMPTY_SPACE,
+    &yy_ei.gfx_element
   },
 
   {
     -1,
     TYPE_BITFIELD,                     CONF_VALUE_8_BIT(2),
-    &xx_ei.access_direction,           MV_ALL_DIRECTIONS
+    &xx_ei.access_direction,           MV_ALL_DIRECTIONS,
+    &yy_ei.access_direction
   },
 
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_16_BIT(2),
-    &xx_ei.collect_score_initial,      10
+    &xx_ei.collect_score_initial,      10,
+    &yy_ei.collect_score_initial
   },
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_16_BIT(3),
-    &xx_ei.collect_count_initial,      1
+    &xx_ei.collect_count_initial,      1,
+    &yy_ei.collect_count_initial
   },
 
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_16_BIT(4),
-    &xx_ei.ce_value_fixed_initial,     0
+    &xx_ei.ce_value_fixed_initial,     0,
+    &yy_ei.ce_value_fixed_initial
   },
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_16_BIT(5),
-    &xx_ei.ce_value_random_initial,    0
+    &xx_ei.ce_value_random_initial,    0,
+    &yy_ei.ce_value_random_initial
   },
   {
     -1,
     TYPE_BOOLEAN,                      CONF_VALUE_8_BIT(3),
-    &xx_ei.use_last_ce_value,          FALSE
+    &xx_ei.use_last_ce_value,          FALSE,
+    &yy_ei.use_last_ce_value
   },
 
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_16_BIT(6),
     &xx_ei.push_delay_fixed,           8,
+    &yy_ei.push_delay_fixed
   },
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_16_BIT(7),
     &xx_ei.push_delay_random,          8,
+    &yy_ei.push_delay_random
   },
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_16_BIT(8),
-    &xx_ei.drop_delay_fixed,           0
+    &xx_ei.drop_delay_fixed,           0,
+    &yy_ei.drop_delay_fixed
   },
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_16_BIT(9),
-    &xx_ei.drop_delay_random,          0
+    &xx_ei.drop_delay_random,          0,
+    &yy_ei.drop_delay_random
   },
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_16_BIT(10),
-    &xx_ei.move_delay_fixed,           0
+    &xx_ei.move_delay_fixed,           0,
+    &yy_ei.move_delay_fixed
   },
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_16_BIT(11),
-    &xx_ei.move_delay_random,          0
+    &xx_ei.move_delay_random,          0,
+    &yy_ei.move_delay_random
   },
 
   {
     -1,
     TYPE_BITFIELD,                     CONF_VALUE_32_BIT(3),
-    &xx_ei.move_pattern,               MV_ALL_DIRECTIONS
+    &xx_ei.move_pattern,               MV_ALL_DIRECTIONS,
+    &yy_ei.move_pattern
   },
   {
     -1,
     TYPE_BITFIELD,                     CONF_VALUE_8_BIT(4),
-    &xx_ei.move_direction_initial,     MV_START_AUTOMATIC
+    &xx_ei.move_direction_initial,     MV_START_AUTOMATIC,
+    &yy_ei.move_direction_initial
   },
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_8_BIT(5),
-    &xx_ei.move_stepsize,              TILEX / 8
+    &xx_ei.move_stepsize,              TILEX / 8,
+    &yy_ei.move_stepsize
   },
 
   {
     -1,
     TYPE_ELEMENT,                      CONF_VALUE_16_BIT(12),
-    &xx_ei.move_enter_element,         EL_EMPTY_SPACE
+    &xx_ei.move_enter_element,         EL_EMPTY_SPACE,
+    &yy_ei.move_enter_element
   },
   {
     -1,
     TYPE_ELEMENT,                      CONF_VALUE_16_BIT(13),
-    &xx_ei.move_leave_element,         EL_EMPTY_SPACE
+    &xx_ei.move_leave_element,         EL_EMPTY_SPACE,
+    &yy_ei.move_leave_element
   },
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_8_BIT(6),
-    &xx_ei.move_leave_type,            LEAVE_TYPE_UNLIMITED
+    &xx_ei.move_leave_type,            LEAVE_TYPE_UNLIMITED,
+    &yy_ei.move_leave_type
   },
 
   {
     -1,
-    TYPE_BOOLEAN,                      CONF_VALUE_8_BIT(7),
-    &xx_ei.slippery_type,              SLIPPERY_ANY_RANDOM
+    TYPE_INTEGER,                      CONF_VALUE_8_BIT(7),
+    &xx_ei.slippery_type,              SLIPPERY_ANY_RANDOM,
+    &yy_ei.slippery_type
   },
 
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_8_BIT(8),
-    &xx_ei.explosion_type,             EXPLODES_3X3
+    &xx_ei.explosion_type,             EXPLODES_3X3,
+    &yy_ei.explosion_type
   },
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_16_BIT(14),
-    &xx_ei.explosion_delay,            16
+    &xx_ei.explosion_delay,            16,
+    &yy_ei.explosion_delay
   },
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_16_BIT(15),
-    &xx_ei.ignition_delay,             8
+    &xx_ei.ignition_delay,             8,
+    &yy_ei.ignition_delay
   },
 
   {
     -1,
     TYPE_CONTENT_LIST,                 CONF_VALUE_BYTES(2),
     &xx_ei.content,                    EL_EMPTY_SPACE,
+    &yy_ei.content,
     &xx_num_contents,                  1, 1
   },
 
@@ -650,13 +674,15 @@ static struct ElementFileConfig custom_element_conf[] =
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_8_BIT(9),
-    &xx_ei.num_change_pages,           -1      /* always save this value */
+    &xx_ei.num_change_pages,           -1,     /* value must always be saved */
+    &yy_ei.num_change_pages
   },
 
   {
     -1,
     -1,                                        -1,
     NULL,                              -1,
+    NULL
   },
 };
 
@@ -667,9 +693,11 @@ static struct ElementFileConfig custom_element_change_conf[] =
   {
     -1,
     TYPE_INTEGER,                      CONF_VALUE_8_BIT(1),
-    &xx_current_change_page,           -1
+    &xx_current_change_page,           -1      /* value must always be saved */
   },
 
+  /* ---------- (the remaining entries can be in any order) ----------------- */
+
   {
     -1,
     TYPE_BOOLEAN,                      CONF_VALUE_8_BIT(2),
@@ -679,12 +707,12 @@ static struct ElementFileConfig custom_element_change_conf[] =
   {
     -1,
     TYPE_BITFIELD,                     CONF_VALUE_32_BIT(1),
-    &xx_event_bits_0_31,               0
+    &xx_event_bits[0],                 0
   },
   {
     -1,
     TYPE_BITFIELD,                     CONF_VALUE_32_BIT(2),
-    &xx_event_bits_32_63,              0
+    &xx_event_bits[1],                 0
   },
 
   {
@@ -786,7 +814,7 @@ static struct ElementFileConfig custom_element_change_conf[] =
   {
     -1,
     TYPE_CONTENT_LIST,                 CONF_VALUE_BYTES(1),
-    &xx_change.target_content,         EL_EMPTY_SPACE,
+    &xx_change.target_content,         EL_EMPTY_SPACE, NULL,
     &xx_num_contents,                  1, 1
   },
 
@@ -802,7 +830,7 @@ static struct ElementFileConfig group_element_conf[] =
   {
     -1,
     TYPE_STRING,                       CONF_VALUE_BYTES(1),
-    &xx_ei.description[0],             -1,
+    &xx_ei.description[0],             -1, NULL,
     &xx_default_description_length,    -1, MAX_ELEMENT_NAME_LEN,
     &xx_default_description[0]
   },
@@ -827,7 +855,7 @@ static struct ElementFileConfig group_element_conf[] =
   {
     -1,
     TYPE_ELEMENT_LIST,                 CONF_VALUE_BYTES(2),
-    &xx_group.element[0],              EL_EMPTY_SPACE,
+    &xx_group.element[0],              EL_EMPTY_SPACE, NULL,
     &xx_group.num_elements,            1, MAX_ELEMENTS_IN_GROUP
   },
 
@@ -860,6 +888,42 @@ filetype_id_list[] =
 /* level file functions                                                      */
 /* ========================================================================= */
 
+static void resetEventFlags(struct ElementChangeInfo *change)
+{
+  int i;
+
+  for (i = 0; i < NUM_CHANGE_EVENTS; i++)
+    change->has_event[i] = FALSE;
+}
+
+static void resetEventBits()
+{
+  int i;
+
+  for (i = 0; i < NUM_CE_BITFIELDS; i++)
+    xx_event_bits[i] = 0;
+}
+
+static void setEventFlagsFromEventBits(struct ElementChangeInfo *change)
+{
+  int i;
+
+  /* important: only change event flag if corresponding event bit is set */
+  for (i = 0; i < NUM_CHANGE_EVENTS; i++)
+    if (xx_event_bits[CH_EVENT_BITFIELD_NR(i)] & CH_EVENT_BIT(i))
+      change->has_event[i] = TRUE;
+}
+
+static void setEventBitsFromEventFlags(struct ElementChangeInfo *change)
+{
+  int i;
+
+  /* important: only change event bit if corresponding event flag is set */
+  for (i = 0; i < NUM_CHANGE_EVENTS; i++)
+    if (change->has_event[i])
+      xx_event_bits[CH_EVENT_BITFIELD_NR(i)] |= CH_EVENT_BIT(i);
+}
+
 static char *getDefaultElementDescription(struct ElementInfo *ei)
 {
   static char description[MAX_ELEMENT_NAME_LEN + 1];
@@ -887,36 +951,34 @@ static void setElementDescriptionToDefault(struct ElementInfo *ei)
     ei->description[i] = default_description[i];
 }
 
-static void setLevelInfoToDefaultsFromConfigList(struct LevelInfo *level)
+static void setConfigToDefaultsFromConfigList(struct ElementFileConfig *config)
 {
   int i;
 
-  li = *level;         /* copy level data into temporary buffer */
-
-  for (i = 0; element_conf[i].data_type != -1; i++)
+  for (i = 0; config[i].data_type != -1; i++)
   {
-    int default_value = element_conf[i].default_value;
-    int data_type = element_conf[i].data_type;
-    int conf_type = element_conf[i].conf_type;
+    int default_value = config[i].default_value;
+    int data_type = config[i].data_type;
+    int conf_type = config[i].conf_type;
     int byte_mask = conf_type & CONF_MASK_BYTES;
 
     if (byte_mask == CONF_MASK_MULTI_BYTES)
     {
-      int default_num_entities = element_conf[i].default_num_entities;
-      int max_num_entities = element_conf[i].max_num_entities;
+      int default_num_entities = config[i].default_num_entities;
+      int max_num_entities = config[i].max_num_entities;
 
-      *(int *)(element_conf[i].num_entities) = default_num_entities;
+      *(int *)(config[i].num_entities) = default_num_entities;
 
       if (data_type == TYPE_STRING)
       {
-       char *default_string = element_conf[i].default_string;
-       char *string = (char *)(element_conf[i].value);
+       char *default_string = config[i].default_string;
+       char *string = (char *)(config[i].value);
 
        strncpy(string, default_string, max_num_entities);
       }
       else if (data_type == TYPE_ELEMENT_LIST)
       {
-       int *element_array = (int *)(element_conf[i].value);
+       int *element_array = (int *)(config[i].value);
        int j;
 
        for (j = 0; j < max_num_entities; j++)
@@ -924,7 +986,7 @@ static void setLevelInfoToDefaultsFromConfigList(struct LevelInfo *level)
       }
       else if (data_type == TYPE_CONTENT_LIST)
       {
-       struct Content *content = (struct Content *)(element_conf[i].value);
+       struct Content *content = (struct Content *)(config[i].value);
        int c, x, y;
 
        for (c = 0; c < max_num_entities; c++)
@@ -936,15 +998,152 @@ static void setLevelInfoToDefaultsFromConfigList(struct LevelInfo *level)
     else       /* constant size configuration data (1, 2 or 4 bytes) */
     {
       if (data_type == TYPE_BOOLEAN)
-       *(boolean *)(element_conf[i].value) = default_value;
+       *(boolean *)(config[i].value) = default_value;
       else
-       *(int *)    (element_conf[i].value) = default_value;
+       *(int *)    (config[i].value) = default_value;
     }
   }
+}
 
-  *level = li;         /* copy temporary buffer back to level data */
+static void copyConfigFromConfigList(struct ElementFileConfig *config)
+{
+  int i;
+
+  for (i = 0; config[i].data_type != -1; i++)
+  {
+    int data_type = config[i].data_type;
+    int conf_type = config[i].conf_type;
+    int byte_mask = conf_type & CONF_MASK_BYTES;
+
+    if (byte_mask == CONF_MASK_MULTI_BYTES)
+    {
+      int max_num_entities = config[i].max_num_entities;
+
+      if (data_type == TYPE_STRING)
+      {
+       char *string      = (char *)(config[i].value);
+       char *string_copy = (char *)(config[i].value_copy);
+
+       strncpy(string_copy, string, max_num_entities);
+      }
+      else if (data_type == TYPE_ELEMENT_LIST)
+      {
+       int *element_array      = (int *)(config[i].value);
+       int *element_array_copy = (int *)(config[i].value_copy);
+       int j;
+
+       for (j = 0; j < max_num_entities; j++)
+         element_array_copy[j] = element_array[j];
+      }
+      else if (data_type == TYPE_CONTENT_LIST)
+      {
+       struct Content *content      = (struct Content *)(config[i].value);
+       struct Content *content_copy = (struct Content *)(config[i].value_copy);
+       int c, x, y;
+
+       for (c = 0; c < max_num_entities; c++)
+         for (y = 0; y < 3; y++)
+           for (x = 0; x < 3; x++)
+             content_copy[c].e[x][y] = content[c].e[x][y];
+      }
+    }
+    else       /* constant size configuration data (1, 2 or 4 bytes) */
+    {
+      if (data_type == TYPE_BOOLEAN)
+       *(boolean *)(config[i].value_copy) = *(boolean *)(config[i].value);
+      else
+       *(int *)    (config[i].value_copy) = *(int *)    (config[i].value);
+    }
+  }
 }
 
+#if 1
+void copyElementInfo(struct ElementInfo *ei_from, struct ElementInfo *ei_to)
+{
+#if 1
+  int i;
+#else
+  int i, x, y;
+#endif
+
+#if 1
+  xx_ei = *ei_from;    /* copy element data into temporary buffer */
+  yy_ei = *ei_to;      /* copy element data into temporary buffer */
+
+  copyConfigFromConfigList(custom_element_conf);
+
+  *ei_from = xx_ei;
+  *ei_to   = yy_ei;
+#endif
+
+#if 0
+  /* ---------- copy element description ---------- */
+  for (i = 0; i < MAX_ELEMENT_NAME_LEN + 1; i++)
+    ei_to->description[i] = ei_from->description[i];
+
+  /* ---------- copy element base properties ---------- */
+  ei_to->properties[EP_BITFIELD_BASE_NR] =
+    ei_from->properties[EP_BITFIELD_BASE_NR];
+
+  /* ---------- copy custom property values ---------- */
+
+  ei_to->use_gfx_element = ei_from->use_gfx_element;
+  ei_to->gfx_element = ei_from->gfx_element;
+
+  ei_to->access_direction = ei_from->access_direction;
+
+  ei_to->collect_score_initial = ei_from->collect_score_initial;
+  ei_to->collect_count_initial = ei_from->collect_count_initial;
+
+  ei_to->ce_value_fixed_initial = ei_from->ce_value_fixed_initial;
+  ei_to->ce_value_random_initial = ei_from->ce_value_random_initial;
+  ei_to->use_last_ce_value = ei_from->use_last_ce_value;
+
+  ei_to->push_delay_fixed = ei_from->push_delay_fixed;
+  ei_to->push_delay_random = ei_from->push_delay_random;
+  ei_to->drop_delay_fixed = ei_from->drop_delay_fixed;
+  ei_to->drop_delay_random = ei_from->drop_delay_random;
+  ei_to->move_delay_fixed = ei_from->move_delay_fixed;
+  ei_to->move_delay_random = ei_from->move_delay_random;
+
+  ei_to->move_pattern = ei_from->move_pattern;
+  ei_to->move_direction_initial = ei_from->move_direction_initial;
+  ei_to->move_stepsize = ei_from->move_stepsize;
+
+  ei_to->move_enter_element = ei_from->move_enter_element;
+  ei_to->move_leave_element = ei_from->move_leave_element;
+  ei_to->move_leave_type = ei_from->move_leave_type;
+
+  ei_to->slippery_type = ei_from->slippery_type;
+
+  ei_to->explosion_type = ei_from->explosion_type;
+  ei_to->explosion_delay = ei_from->explosion_delay;
+  ei_to->ignition_delay = ei_from->ignition_delay;
+
+  for (y = 0; y < 3; y++)
+    for (x = 0; x < 3; x++)
+      ei_to->content.e[x][y] = ei_from->content.e[x][y];
+#endif
+
+  /* ---------- reinitialize and copy change pages ---------- */
+
+  ei_to->num_change_pages = ei_from->num_change_pages;
+  ei_to->current_change_page = ei_from->current_change_page;
+
+  setElementChangePages(ei_to, ei_to->num_change_pages);
+
+  for (i = 0; i < ei_to->num_change_pages; i++)
+    ei_to->change_page[i] = ei_from->change_page[i];
+
+  /* ---------- copy group element info ---------- */
+  if (ei_from->group != NULL && ei_to->group != NULL)  /* group or internal */
+    *ei_to->group = *ei_from->group;
+
+  /* mark this custom element as modified */
+  ei_to->modified_settings = TRUE;
+}
+#endif
+
 void setElementChangePages(struct ElementInfo *ei, int change_pages)
 {
   int change_page_size = sizeof(struct ElementChangeInfo);
@@ -962,8 +1161,22 @@ void setElementChangePages(struct ElementInfo *ei, int change_pages)
 
 void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
 {
+#if 0
   int i, x, y;
+#endif
 
+#if 1
+  xx_change = *change;         /* copy change data into temporary buffer */
+  xx_num_contents = 1;
+
+  setConfigToDefaultsFromConfigList(custom_element_change_conf);
+
+  *change = xx_change;
+
+  resetEventFlags(change);
+#endif
+
+#if 0
   change->can_change = FALSE;
 
   for (i = 0; i < NUM_CHANGE_EVENTS; i++)
@@ -996,6 +1209,7 @@ void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
   for (x = 0; x < 3; x++)
     for (y = 0; y < 3; y++)
       change->target_content.e[x][y] = EL_EMPTY_SPACE;
+#endif
 
   change->direct_action = 0;
   change->other_action = 0;
@@ -1008,13 +1222,24 @@ void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
 static void setLevelInfoToDefaults(struct LevelInfo *level)
 {
   static boolean clipboard_elements_initialized = FALSE;
+#if 0
   int i, j, x, y;
+#else
+  int i, x, y;
+#endif
 
 #if 1
   InitElementPropertiesStatic();
 #endif
 
-  setLevelInfoToDefaultsFromConfigList(level);
+#if 1
+  li = *level;         /* copy level data into temporary buffer */
+
+  setConfigToDefaultsFromConfigList(element_conf);
+
+  *level = li;         /* copy temporary buffer back to level data */
+#endif
+
   setLevelInfoToDefaults_EM();
 
   level->native_em_level = &native_em_level;
@@ -1049,6 +1274,7 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
 
   level->amoeba_content = EL_DIAMOND;
 
+#if 0
   level->game_of_life[0] = 2;
   level->game_of_life[1] = 3;
   level->game_of_life[2] = 3;
@@ -1058,6 +1284,7 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
   level->biomaze[1] = 3;
   level->biomaze[2] = 3;
   level->biomaze[3] = 3;
+#endif
 
 #if 0
   level->double_speed = FALSE;
@@ -1096,12 +1323,12 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
   level->wind_direction_initial = MV_NONE;
   level->ball_random = FALSE;
   level->ball_state_initial = FALSE;
+
   for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
     for (x = 0; x < 3; x++)
       for (y = 0; y < 3; y++)
        level->ball_content[i].e[x][y] = EL_EMPTY;
-#endif
-#if 0
+
   for (i = 0; i < 16; i++)
     level->android_array[i] = FALSE;
 #endif
@@ -1141,7 +1368,21 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
     int element = i;
     struct ElementInfo *ei = &element_info[element];
 
+#if 1
+    if (IS_CUSTOM_ELEMENT(element) ||
+       IS_GROUP_ELEMENT(element) ||
+       IS_INTERNAL_ELEMENT(element))
+    {
+      xx_ei = *ei;     /* copy element data into temporary buffer */
+
+      setConfigToDefaultsFromConfigList(custom_element_conf);
+
+      *ei = xx_ei;
+    }
+#endif
+
     /* never initialize clipboard elements after the very first time */
+    /* (to be able to use clipboard elements between several levels) */
     if (IS_CLIPBOARD_ELEMENT(element) && clipboard_elements_initialized)
       continue;
 
@@ -1164,8 +1405,10 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
        strcpy(ei->description, ei->editor_description);
 #endif
 
+#if 0
       ei->use_gfx_element = FALSE;
       ei->gfx_element = EL_EMPTY_SPACE;
+#endif
 
       ei->modified_settings = FALSE;
     }
@@ -1173,6 +1416,7 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
     if (IS_CUSTOM_ELEMENT(element) ||
        IS_INTERNAL_ELEMENT(element))
     {
+#if 0
       ei->access_direction = MV_ALL_DIRECTIONS;
 
       ei->collect_score_initial = 10;  /* special default */
@@ -1206,6 +1450,7 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
       for (x = 0; x < 3; x++)
        for (y = 0; y < 3; y++)
          ei->content.e[x][y] = EL_EMPTY_SPACE;
+#endif
 
       ei->access_type = 0;
       ei->access_layer = 0;
@@ -1233,8 +1478,10 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
 #endif
 #endif
 
+#if 0
       /* now set default properties */
       SET_PROPERTY(element, EP_CAN_MOVE_INTO_ACID, TRUE);
+#endif
     }
 
     if (IS_GROUP_ELEMENT(element) ||
@@ -1248,6 +1495,15 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
 
       group = ei->group;
 
+#if 1
+      xx_group = *group;       /* copy group data into temporary buffer */
+
+      setConfigToDefaultsFromConfigList(group_element_conf);
+
+      *group = xx_group;
+#endif
+
+#if 0
       for (j = 0; j < MAX_ELEMENTS_IN_GROUP; j++)
        group->element[j] = EL_EMPTY_SPACE;
 
@@ -1255,6 +1511,7 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
       group->num_elements = 1;
 
       group->choice_mode = ANIM_RANDOM;
+#endif
     }
   }
 
@@ -1900,12 +2157,12 @@ static int LoadLevel_CUS1(FILE *file, int chunk_size, struct LevelInfo *level)
 
 #if 1
     if (IS_CUSTOM_ELEMENT(element))
-      element_info[element].properties[EP_BITFIELD_BASE] = properties;
+      element_info[element].properties[EP_BITFIELD_BASE_NR] = properties;
     else
       Error(ERR_WARN, "invalid custom element number %d", element);
 #else
     if (IS_CUSTOM_ELEMENT(element))
-      Properties[element][EP_BITFIELD_BASE] = properties;
+      Properties[element][EP_BITFIELD_BASE_NR] = properties;
     else
       Error(ERR_WARN, "invalid custom element number %d", element);
 #endif
@@ -1970,9 +2227,9 @@ static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level)
     ei->description[MAX_ELEMENT_NAME_LEN] = 0;
 
 #if 1
-    ei->properties[EP_BITFIELD_BASE] = getFile32BitBE(file);
+    ei->properties[EP_BITFIELD_BASE_NR] = getFile32BitBE(file);
 #else
-    Properties[element][EP_BITFIELD_BASE] = getFile32BitBE(file);
+    Properties[element][EP_BITFIELD_BASE_NR] = getFile32BitBE(file);
 #endif
 
     /* some free bytes for future properties and padding */
@@ -2061,9 +2318,9 @@ static int LoadLevel_CUS4(FILE *file, int chunk_size, struct LevelInfo *level)
   ei->description[MAX_ELEMENT_NAME_LEN] = 0;
 
 #if 1
-  ei->properties[EP_BITFIELD_BASE] = getFile32BitBE(file);
+  ei->properties[EP_BITFIELD_BASE_NR] = getFile32BitBE(file);
 #else
-  Properties[element][EP_BITFIELD_BASE] = getFile32BitBE(file);
+  Properties[element][EP_BITFIELD_BASE_NR] = getFile32BitBE(file);
 #endif
   ReadUnusedBytesFromFile(file, 4);    /* reserved for more base properties */
 
@@ -2492,8 +2749,9 @@ static int LoadLevel_CUSX(FILE *file, int chunk_size, struct LevelInfo *level)
   int element = getFile16BitBE(file);
   int real_chunk_size = 2;
   struct ElementInfo *ei = &element_info[element];
+  int i;
 
-#if 1
+#if 0
   printf("::: CUSX: loading element '%s' ...\n", EL_NAME(element));
 #endif
 
@@ -2524,36 +2782,34 @@ static int LoadLevel_CUSX(FILE *file, int chunk_size, struct LevelInfo *level)
          EL_NAME(element));
 
     ei->num_change_pages = 1;
+
     setElementChangePages(ei, 1);
+    setElementChangeInfoToDefaults(ei->change);
 
     return real_chunk_size;
   }
 
+  /* initialize number of change pages stored for this custom element */
   setElementChangePages(ei, ei->num_change_pages);
+  for (i = 0; i < ei->num_change_pages; i++)
+    setElementChangeInfoToDefaults(&ei->change_page[i]);
 
+  /* start with reading properties for the first change page */
   xx_current_change_page = 0;
 
-  xx_event_bits_0_31 = 0;
-  xx_event_bits_32_63 = 0;
-
   while (!feof(file))
   {
     struct ElementChangeInfo *change = &ei->change_page[xx_current_change_page];
-    int i;
 
     xx_change = *change;       /* copy change data into temporary buffer */
 
+    resetEventBits();          /* reset bits; change page might have changed */
+
     real_chunk_size += LoadLevel_MicroChunk(file,custom_element_change_conf,-1);
 
     *change = xx_change;
 
-    for (i = 0; i < NUM_CHANGE_EVENTS; i++)
-      if ((i <  32 && xx_event_bits_0_31  & (1 << i)) ||
-         (i >= 32 && xx_event_bits_32_63 & (1 << (i - 32))))
-       change->has_event[i] = TRUE;
-
-    xx_event_bits_0_31 = 0;
-    xx_event_bits_32_63 = 0;
+    setEventFlagsFromEventBits(change);
 
     if (real_chunk_size >= chunk_size)
       break;
@@ -4501,23 +4757,23 @@ static void SaveLevel_CUS1(FILE *file, struct LevelInfo *level,
 #if 1
     struct ElementInfo *ei = &element_info[element];
 
-    if (ei->properties[EP_BITFIELD_BASE] != EP_BITMASK_DEFAULT)
+    if (ei->properties[EP_BITFIELD_BASE_NR] != EP_BITMASK_DEFAULT)
     {
       if (check < num_changed_custom_elements)
       {
        putFile16BitBE(file, element);
-       putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE]);
+       putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE_NR]);
       }
 
       check++;
     }
 #else
-    if (Properties[element][EP_BITFIELD_BASE] != EP_BITMASK_DEFAULT)
+    if (Properties[element][EP_BITFIELD_BASE_NR] != EP_BITMASK_DEFAULT)
     {
       if (check < num_changed_custom_elements)
       {
        putFile16BitBE(file, element);
-       putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE]);
+       putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE_NR]);
       }
 
       check++;
@@ -4582,9 +4838,9 @@ static void SaveLevel_CUS3(FILE *file, struct LevelInfo *level,
          putFile8Bit(file, ei->description[j]);
 
 #if 1
-       putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE]);
+       putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE_NR]);
 #else
-       putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE]);
+       putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE_NR]);
 #endif
 
        /* some free bytes for future properties and padding */
@@ -4646,6 +4902,7 @@ static void SaveLevel_CUS3(FILE *file, struct LevelInfo *level,
 }
 #endif
 
+#if 0
 static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
 {
   struct ElementInfo *ei = &element_info[element];
@@ -4659,9 +4916,9 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
     putFile8Bit(file, ei->description[i]);
 
 #if 1
-  putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE]);
+  putFile32BitBE(file, ei->properties[EP_BITFIELD_BASE_NR]);
 #else
-  putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE]);
+  putFile32BitBE(file, Properties[element][EP_BITFIELD_BASE_NR]);
 #endif
   WriteUnusedBytesToFile(file, 4);     /* reserved for more base properties */
 
@@ -4766,7 +5023,9 @@ static void SaveLevel_CUS4(FILE *file, struct LevelInfo *level, int element)
     putFile8Bit(file, event_bits);
   }
 }
+#endif
 
+#if 0
 static void SaveLevel_GRP1(FILE *file, struct LevelInfo *level, int element)
 {
   struct ElementInfo *ei = &element_info[element];
@@ -4791,6 +5050,7 @@ static void SaveLevel_GRP1(FILE *file, struct LevelInfo *level, int element)
   for (i = 0; i < MAX_ELEMENTS_IN_GROUP; i++)
     putFile16BitBE(file, group->element[i]);
 }
+#endif
 
 static int SaveLevel_MicroChunk(FILE *file, struct ElementFileConfig *entry)
 {
@@ -5052,7 +5312,7 @@ static int SaveLevel_CUSX(FILE *file, struct LevelInfo *level, int element)
 {
   struct ElementInfo *ei = &element_info[element];
   int chunk_size = 0;
-  int i;
+  int i, j;
 
   chunk_size += putFile16BitBE(file, element);
 
@@ -5090,22 +5350,17 @@ static int SaveLevel_CUSX(FILE *file, struct LevelInfo *level, int element)
           i, xx_change.action_arg);
 #endif
 
-    xx_event_bits_0_31 = 0;
-    xx_event_bits_32_63 = 0;
+    resetEventBits();
+    setEventBitsFromEventFlags(change);
 
-    for (i = 0; i < NUM_CHANGE_EVENTS; i++)
-    {
-      if (change->has_event[i])
-      {
-       if (i < 32)
-         xx_event_bits_0_31 |= (1 << i);
-       else
-         xx_event_bits_32_63 |= (1 << (i - 32));
-      }
-    }
+    for (j = 0; custom_element_change_conf[j].data_type != -1; j++)
+      chunk_size += SaveLevel_MicroChunk(file, &custom_element_change_conf[j]);
 
-    for (i = 0; custom_element_change_conf[i].data_type != -1; i++)
-      chunk_size += SaveLevel_MicroChunk(file, &custom_element_change_conf[i]);
+#if 0
+    if (element == EL_CUSTOM_START)
+      printf("::: - saving change page %d / %d (%d bytes)\n",
+            i, ei->num_change_pages, chunk_size);
+#endif
   }
 
   return chunk_size;
@@ -5214,7 +5469,7 @@ static void SaveLevelFromFilename(struct LevelInfo *level, char *filename)
   /* if not using template level, check for non-default custom/group elements */
   if (!level->use_custom_template)
   {
-#if 1
+#if 0
     for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
     {
       int element = EL_CUSTOM_START + i;
@@ -5227,9 +5482,7 @@ static void SaveLevelFromFilename(struct LevelInfo *level, char *filename)
        SaveLevel_CUS4(file, level, element);
       }
     }
-#endif
 
-#if 1
     for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
     {
       int element = EL_GROUP_START + i;
@@ -5276,15 +5529,8 @@ static void SaveLevelFromFilename(struct LevelInfo *level, char *filename)
        putFileChunkBE(file, "CUSX", cusx_chunk_size);
        SaveLevel_CUSX(file, level, element);
       }
-
-#if 0
-      if (i == 1)
-       break;
-#endif
     }
-#endif
 
-#if 1
     for (i = 0; i < NUM_GROUP_ELEMENTS; i++)
     {
       int element = EL_GROUP_START + i;
@@ -5300,11 +5546,6 @@ static void SaveLevelFromFilename(struct LevelInfo *level, char *filename)
        putFileChunkBE(file, "GRPX", grpx_chunk_size);
        SaveLevel_GRPX(file, level, element);
       }
-
-#if 0
-      if (i == 1)
-       break;
-#endif
     }
 #endif
   }