rnd-20030829-R-src
authorHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2003 00:01:13 +0000 (02:01 +0200)
committerHolger Schemel <info@artsoft.org>
Sat, 30 Aug 2014 08:43:32 +0000 (10:43 +0200)
12 files changed:
CHANGES
src/conftime.h
src/editor.c
src/files.c
src/files.h
src/game.c
src/init.c
src/libgame/gadgets.c
src/libgame/gadgets.h
src/libgame/text.c
src/libgame/text.h
src/main.h

diff --git a/CHANGES b/CHANGES
index 9ee229b4068192546b86a3161a5e8c1a3a769c70..e57b06e90501acaaa2f81ca365ec39209c4b8e77 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -3,6 +3,7 @@ Release Version 3.0.3 [?? ??? ????]
        - fixed bug (missing array boundary check) which could crash the game
        - fixed problem with setting mouse cursor in SDL version in fullscreen
        - fixed problem with flickering when drawing toon animations
+       - fixed problem with player animation when snapping and moving
 
 Release Version 3.0.2 [22 AUG 2003]
 -----------------------------------
index 6ffa2c350fd9fcecf602dec269a5051bd3ff2ccf..e72f2c2bbd8d0cc10647d9917fd896f5ac510776 100644 (file)
@@ -1 +1 @@
-#define COMPILE_DATE_STRING "[2003-08-29 22:16]"
+#define COMPILE_DATE_STRING "[2003-08-24 19:50]"
index 12053e073e7d9f6745413d40669c627a036cb20b..4a47194a4066bd6b346616bbca718db1f1a1c7b8 100644 (file)
 #define ED_SETTINGS2_YPOS              (ED_SETTINGS1_YPOS + 12 * TILEY - 2)
 
 /* values for counter gadgets */
+#define ED_COUNT_PUSH_DELAY_RND_XPOS   (ED_SETTINGS_XPOS(1) + 16 * MINI_TILEX)
+#define ED_COUNT_MOVE_DELAY_RND_XPOS   ED_COUNT_PUSH_DELAY_RND_XPOS
+#define ED_COUNT_CHANGE_DELAY_RND_XPOS (ED_SETTINGS_XPOS(1) + 13 * MINI_TILEX)
+
 #define ED_COUNTER_YSTART              (ED_SETTINGS1_YPOS + 2 * TILEY)
 #define ED_COUNTER_YDISTANCE           (3 * MINI_TILEY)
 #define ED_COUNTER_YPOS(n)             (ED_COUNTER_YSTART + \
                                         6 * (n / 4) * MINI_TILEY)
 
 /* custom change target */
+#define ED_AREA_ELEM_CONTENT2_XPOS     (20 * MINI_TILEX)
 #define ED_AREA_ELEM_CONTENT2_YPOS     (ED_SETTINGS_YPOS(2) + \
                                         ED_GADGET_DISTANCE)
 /* optional custom graphic */
+#define ED_AREA_ELEM_CONTENT3_XPOS     (24 * MINI_TILEX)
 #define ED_AREA_ELEM_CONTENT3_YPOS     (ED_SETTINGS_YPOS(1) + \
                                         ED_GADGET_DISTANCE)
 /* custom element content */
 #define ED_AREA_ELEM_CONTENT4_YPOS     (ED_SETTINGS_YPOS(12) + \
                                         ED_GADGET_DISTANCE - MINI_TILEY)
 /* custom change trigger element */
+#define ED_AREA_ELEM_CONTENT5_XPOS     (28 * MINI_TILEX)
 #define ED_AREA_ELEM_CONTENT5_YPOS     (ED_SETTINGS_YPOS(7) + \
                                         ED_GADGET_DISTANCE)
 /* extended custom change target */
                                         ED_GADGET_DISTANCE - MINI_TILEY)
 
 /* values for random placement background drawing area */
+#define ED_AREA_RANDOM_BACKGROUND_XPOS (29 * MINI_TILEX)
 #define ED_AREA_RANDOM_BACKGROUND_YPOS (31 * MINI_TILEY)
 
 /* values for scrolling gadgets for drawing area */
 #define GADGET_ID_ELEMENT_CONTENT_DOWN (GADGET_ID_COUNTER_FIRST + 24)
 #define GADGET_ID_ELEMENT_CONTENT_TEXT (GADGET_ID_COUNTER_FIRST + 25)
 #define GADGET_ID_ELEMENT_CONTENT_UP   (GADGET_ID_COUNTER_FIRST + 26)
-#define GADGET_ID_ENVELOPE_XSIZE_DOWN  (GADGET_ID_COUNTER_FIRST + 27)
-#define GADGET_ID_ENVELOPE_XSIZE_TEXT  (GADGET_ID_COUNTER_FIRST + 28)
-#define GADGET_ID_ENVELOPE_XSIZE_UP    (GADGET_ID_COUNTER_FIRST + 29)
-#define GADGET_ID_ENVELOPE_YSIZE_DOWN  (GADGET_ID_COUNTER_FIRST + 30)
-#define GADGET_ID_ENVELOPE_YSIZE_TEXT  (GADGET_ID_COUNTER_FIRST + 31)
-#define GADGET_ID_ENVELOPE_YSIZE_UP    (GADGET_ID_COUNTER_FIRST + 32)
-#define GADGET_ID_CUSTOM_SCORE_DOWN    (GADGET_ID_COUNTER_FIRST + 33)
-#define GADGET_ID_CUSTOM_SCORE_TEXT    (GADGET_ID_COUNTER_FIRST + 34)
-#define GADGET_ID_CUSTOM_SCORE_UP      (GADGET_ID_COUNTER_FIRST + 35)
-#define GADGET_ID_CUSTOM_GEMCOUNT_DOWN (GADGET_ID_COUNTER_FIRST + 36)
-#define GADGET_ID_CUSTOM_GEMCOUNT_TEXT (GADGET_ID_COUNTER_FIRST + 37)
-#define GADGET_ID_CUSTOM_GEMCOUNT_UP   (GADGET_ID_COUNTER_FIRST + 38)
-#define GADGET_ID_PUSH_DELAY_FIX_DOWN  (GADGET_ID_COUNTER_FIRST + 39)
-#define GADGET_ID_PUSH_DELAY_FIX_TEXT  (GADGET_ID_COUNTER_FIRST + 40)
-#define GADGET_ID_PUSH_DELAY_FIX_UP    (GADGET_ID_COUNTER_FIRST + 41)
-#define GADGET_ID_PUSH_DELAY_RND_DOWN  (GADGET_ID_COUNTER_FIRST + 42)
-#define GADGET_ID_PUSH_DELAY_RND_TEXT  (GADGET_ID_COUNTER_FIRST + 43)
-#define GADGET_ID_PUSH_DELAY_RND_UP    (GADGET_ID_COUNTER_FIRST + 44)
-#define GADGET_ID_MOVE_DELAY_FIX_DOWN  (GADGET_ID_COUNTER_FIRST + 45)
-#define GADGET_ID_MOVE_DELAY_FIX_TEXT  (GADGET_ID_COUNTER_FIRST + 46)
-#define GADGET_ID_MOVE_DELAY_FIX_UP    (GADGET_ID_COUNTER_FIRST + 47)
-#define GADGET_ID_MOVE_DELAY_RND_DOWN  (GADGET_ID_COUNTER_FIRST + 48)
-#define GADGET_ID_MOVE_DELAY_RND_TEXT  (GADGET_ID_COUNTER_FIRST + 49)
-#define GADGET_ID_MOVE_DELAY_RND_UP    (GADGET_ID_COUNTER_FIRST + 50)
-#define GADGET_ID_CHANGE_DELAY_FIX_DOWN        (GADGET_ID_COUNTER_FIRST + 51)
-#define GADGET_ID_CHANGE_DELAY_FIX_TEXT        (GADGET_ID_COUNTER_FIRST + 52)
-#define GADGET_ID_CHANGE_DELAY_FIX_UP  (GADGET_ID_COUNTER_FIRST + 53)
-#define GADGET_ID_CHANGE_DELAY_RND_DOWN        (GADGET_ID_COUNTER_FIRST + 54)
-#define GADGET_ID_CHANGE_DELAY_RND_TEXT        (GADGET_ID_COUNTER_FIRST + 55)
-#define GADGET_ID_CHANGE_DELAY_RND_UP  (GADGET_ID_COUNTER_FIRST + 56)
-#define GADGET_ID_CHANGE_CONT_RND_DOWN (GADGET_ID_COUNTER_FIRST + 57)
-#define GADGET_ID_CHANGE_CONT_RND_TEXT (GADGET_ID_COUNTER_FIRST + 58)
-#define GADGET_ID_CHANGE_CONT_RND_UP   (GADGET_ID_COUNTER_FIRST + 59)
+#define GADGET_ID_CUSTOM_SCORE_DOWN    (GADGET_ID_COUNTER_FIRST + 27)
+#define GADGET_ID_CUSTOM_SCORE_TEXT    (GADGET_ID_COUNTER_FIRST + 28)
+#define GADGET_ID_CUSTOM_SCORE_UP      (GADGET_ID_COUNTER_FIRST + 29)
+#define GADGET_ID_CUSTOM_GEMCOUNT_DOWN (GADGET_ID_COUNTER_FIRST + 30)
+#define GADGET_ID_CUSTOM_GEMCOUNT_TEXT (GADGET_ID_COUNTER_FIRST + 31)
+#define GADGET_ID_CUSTOM_GEMCOUNT_UP   (GADGET_ID_COUNTER_FIRST + 32)
+#define GADGET_ID_PUSH_DELAY_FIX_DOWN  (GADGET_ID_COUNTER_FIRST + 33)
+#define GADGET_ID_PUSH_DELAY_FIX_TEXT  (GADGET_ID_COUNTER_FIRST + 34)
+#define GADGET_ID_PUSH_DELAY_FIX_UP    (GADGET_ID_COUNTER_FIRST + 35)
+#define GADGET_ID_PUSH_DELAY_RND_DOWN  (GADGET_ID_COUNTER_FIRST + 36)
+#define GADGET_ID_PUSH_DELAY_RND_TEXT  (GADGET_ID_COUNTER_FIRST + 37)
+#define GADGET_ID_PUSH_DELAY_RND_UP    (GADGET_ID_COUNTER_FIRST + 38)
+#define GADGET_ID_MOVE_DELAY_FIX_DOWN  (GADGET_ID_COUNTER_FIRST + 39)
+#define GADGET_ID_MOVE_DELAY_FIX_TEXT  (GADGET_ID_COUNTER_FIRST + 40)
+#define GADGET_ID_MOVE_DELAY_FIX_UP    (GADGET_ID_COUNTER_FIRST + 41)
+#define GADGET_ID_MOVE_DELAY_RND_DOWN  (GADGET_ID_COUNTER_FIRST + 42)
+#define GADGET_ID_MOVE_DELAY_RND_TEXT  (GADGET_ID_COUNTER_FIRST + 43)
+#define GADGET_ID_MOVE_DELAY_RND_UP    (GADGET_ID_COUNTER_FIRST + 44)
+#define GADGET_ID_CHANGE_DELAY_FIX_DOWN        (GADGET_ID_COUNTER_FIRST + 45)
+#define GADGET_ID_CHANGE_DELAY_FIX_TEXT        (GADGET_ID_COUNTER_FIRST + 46)
+#define GADGET_ID_CHANGE_DELAY_FIX_UP  (GADGET_ID_COUNTER_FIRST + 47)
+#define GADGET_ID_CHANGE_DELAY_RND_DOWN        (GADGET_ID_COUNTER_FIRST + 48)
+#define GADGET_ID_CHANGE_DELAY_RND_TEXT        (GADGET_ID_COUNTER_FIRST + 49)
+#define GADGET_ID_CHANGE_DELAY_RND_UP  (GADGET_ID_COUNTER_FIRST + 50)
+#define GADGET_ID_CHANGE_CONT_RND_DOWN (GADGET_ID_COUNTER_FIRST + 51)
+#define GADGET_ID_CHANGE_CONT_RND_TEXT (GADGET_ID_COUNTER_FIRST + 52)
+#define GADGET_ID_CHANGE_CONT_RND_UP   (GADGET_ID_COUNTER_FIRST + 53)
 
 /* drawing area identifiers */
-#define GADGET_ID_DRAWING_AREA_FIRST   (GADGET_ID_COUNTER_FIRST + 60)
+#define GADGET_ID_DRAWING_AREA_FIRST   (GADGET_ID_COUNTER_FIRST + 54)
 
 #define GADGET_ID_DRAWING_LEVEL                (GADGET_ID_DRAWING_AREA_FIRST + 0)
 #define GADGET_ID_ELEMENT_CONTENT_0    (GADGET_ID_DRAWING_AREA_FIRST + 1)
 #define GADGET_ID_LEVEL_AUTHOR         (GADGET_ID_TEXT_INPUT_FIRST + 1)
 #define GADGET_ID_ELEMENT_NAME         (GADGET_ID_TEXT_INPUT_FIRST + 2)
 
-/* text area identifiers */
-#define GADGET_ID_TEXT_AREA_FIRST      (GADGET_ID_TEXT_INPUT_FIRST + 3)
-
-#define GADGET_ID_ENVELOPE_INFO                (GADGET_ID_TEXT_AREA_FIRST + 0)
-
 /* selectbox identifiers */
-#define GADGET_ID_SELECTBOX_FIRST      (GADGET_ID_TEXT_AREA_FIRST + 1)
+#define GADGET_ID_SELECTBOX_FIRST      (GADGET_ID_TEXT_INPUT_FIRST + 3)
 
 #define GADGET_ID_CUSTOM_WALK_TO_ACTION        (GADGET_ID_SELECTBOX_FIRST + 0)
 #define GADGET_ID_CUSTOM_CONSISTENCY   (GADGET_ID_SELECTBOX_FIRST + 1)
 #define GADGET_ID_CHANGE_COLLIDE_ACTION        (GADGET_ID_SELECTBOX_FIRST + 12)
 #define GADGET_ID_CHANGE_OTHER_ACTION  (GADGET_ID_SELECTBOX_FIRST + 13)
 #define GADGET_ID_CHANGE_POWER         (GADGET_ID_SELECTBOX_FIRST + 14)
-#define GADGET_ID_SELECT_CHANGE_PAGE   (GADGET_ID_SELECTBOX_FIRST + 15)
 
 /* textbutton identifiers */
-#define GADGET_ID_TEXTBUTTON_FIRST     (GADGET_ID_SELECTBOX_FIRST + 16)
+#define GADGET_ID_TEXTBUTTON_FIRST     (GADGET_ID_SELECTBOX_FIRST + 15)
 
 #define GADGET_ID_PROPERTIES_INFO      (GADGET_ID_TEXTBUTTON_FIRST + 0)
 #define GADGET_ID_PROPERTIES_CONFIG    (GADGET_ID_TEXTBUTTON_FIRST + 1)
 #define GADGET_ID_PROPERTIES_ADVANCED  (GADGET_ID_TEXTBUTTON_FIRST + 2)
 #define GADGET_ID_SAVE_AS_TEMPLATE     (GADGET_ID_TEXTBUTTON_FIRST + 3)
-#define GADGET_ID_ADD_CHANGE_PAGE      (GADGET_ID_TEXTBUTTON_FIRST + 4)
-#define GADGET_ID_DEL_CHANGE_PAGE      (GADGET_ID_TEXTBUTTON_FIRST + 5)
-
-/* graphicbutton identifiers */
-#define GADGET_ID_GRAPHICBUTTON_FIRST  (GADGET_ID_TEXTBUTTON_FIRST + 6)
-
-#define GADGET_ID_PREV_CHANGE_PAGE     (GADGET_ID_GRAPHICBUTTON_FIRST + 0)
-#define GADGET_ID_NEXT_CHANGE_PAGE     (GADGET_ID_GRAPHICBUTTON_FIRST + 1)
 
 /* gadgets for scrolling of drawing area */
-#define GADGET_ID_SCROLLING_FIRST      (GADGET_ID_GRAPHICBUTTON_FIRST + 2)
+#define GADGET_ID_SCROLLING_FIRST      (GADGET_ID_TEXTBUTTON_FIRST + 4)
 
 #define GADGET_ID_SCROLL_UP            (GADGET_ID_SCROLLING_FIRST + 0)
 #define GADGET_ID_SCROLL_DOWN          (GADGET_ID_SCROLLING_FIRST + 1)
 #define ED_COUNTER_ID_LEVEL_RANDOM     6
 #define ED_COUNTER_ID_ELEMENT_SCORE    7
 #define ED_COUNTER_ID_ELEMENT_CONTENT  8
-#define ED_COUNTER_ID_ENVELOPE_XSIZE   9
-#define ED_COUNTER_ID_ENVELOPE_YSIZE   10
-#define ED_COUNTER_ID_CUSTOM_SCORE     11
-#define ED_COUNTER_ID_CUSTOM_GEMCOUNT  12
-#define ED_COUNTER_ID_PUSH_DELAY_FIX   13
-#define ED_COUNTER_ID_PUSH_DELAY_RND   14
-#define ED_COUNTER_ID_MOVE_DELAY_FIX   15
-#define ED_COUNTER_ID_MOVE_DELAY_RND   16
-#define ED_COUNTER_ID_CHANGE_DELAY_FIX 17
-#define ED_COUNTER_ID_CHANGE_DELAY_RND 18
-#define ED_COUNTER_ID_CHANGE_CONT_RND  19
-
-#define ED_NUM_COUNTERBUTTONS          20
+#define ED_COUNTER_ID_CUSTOM_SCORE     9
+#define ED_COUNTER_ID_CUSTOM_GEMCOUNT  10
+#define ED_COUNTER_ID_PUSH_DELAY_FIX   11
+#define ED_COUNTER_ID_PUSH_DELAY_RND   12
+#define ED_COUNTER_ID_MOVE_DELAY_FIX   13
+#define ED_COUNTER_ID_MOVE_DELAY_RND   14
+#define ED_COUNTER_ID_CHANGE_DELAY_FIX 15
+#define ED_COUNTER_ID_CHANGE_DELAY_RND 16
+#define ED_COUNTER_ID_CHANGE_CONT_RND  17
+
+#define ED_NUM_COUNTERBUTTONS          18
 
 #define ED_COUNTER_ID_LEVEL_FIRST      ED_COUNTER_ID_LEVEL_XSIZE
 #define ED_COUNTER_ID_LEVEL_LAST       ED_COUNTER_ID_LEVEL_RANDOM
 #define ED_TEXTINPUT_ID_LEVEL_FIRST    ED_TEXTINPUT_ID_LEVEL_NAME
 #define ED_TEXTINPUT_ID_LEVEL_LAST     ED_TEXTINPUT_ID_LEVEL_AUTHOR
 
-/* values for text area gadgets */
-#define ED_TEXTAREA_ID_ENVELOPE_INFO   0
-
-#define ED_NUM_TEXTAREAS                       1
-
-#define ED_TEXTAREA_ID_LEVEL_FIRST     ED_TEXTAREA_ID_ENVELOPE
-#define ED_TEXTAREA_ID_LEVEL_LAST      ED_TEXTAREA_ID_ENVELOPE
-
 /* values for selectbox gadgets */
 #define ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE     0
 #define ED_SELECTBOX_ID_CUSTOM_ACCESS_LAYER    1
 #define ED_SELECTBOX_ID_CHANGE_COLLIDE_ACTION  12
 #define ED_SELECTBOX_ID_CHANGE_OTHER_ACTION    13
 #define ED_SELECTBOX_ID_CHANGE_POWER           14
-#define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE     15
 
-#define ED_NUM_SELECTBOX                       16
+#define ED_NUM_SELECTBOX                       15
 
 #define ED_SELECTBOX_ID_CUSTOM_FIRST   ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE
 #define ED_SELECTBOX_ID_CUSTOM_LAST    ED_SELECTBOX_ID_CUSTOM_CONSISTENCY
 
 #define ED_SELECTBOX_ID_CHANGE_FIRST   ED_SELECTBOX_ID_CHANGE_TIME_UNITS
-#define ED_SELECTBOX_ID_CHANGE_LAST    ED_SELECTBOX_ID_SELECT_CHANGE_PAGE
+#define ED_SELECTBOX_ID_CHANGE_LAST    ED_SELECTBOX_ID_CHANGE_POWER
 
 /* values for textbutton gadgets */
 #define ED_TEXTBUTTON_ID_PROPERTIES_INFO       0
 #define ED_TEXTBUTTON_ID_PROPERTIES_CONFIG     1
 #define ED_TEXTBUTTON_ID_PROPERTIES_ADVANCED   2
 #define ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE      3
-#define ED_TEXTBUTTON_ID_ADD_CHANGE_PAGE       4
-#define ED_TEXTBUTTON_ID_DEL_CHANGE_PAGE       5
 
-#define ED_NUM_TEXTBUTTONS                     6
-
-#define ED_TEXTBUTTON_ID_PROPERTIES_FIRST ED_TEXTBUTTON_ID_PROPERTIES_INFO
-#define ED_TEXTBUTTON_ID_PROPERTIES_LAST  ED_TEXTBUTTON_ID_PROPERTIES_ADVANCED
-
-#define ED_TEXTBUTTON_ID_CHANGE_FIRST  ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE
-#define ED_TEXTBUTTON_ID_CHANGE_LAST   ED_TEXTBUTTON_ID_DEL_CHANGE_PAGE
-
-/* values for graphicbutton gadgets */
-#define ED_GRAPHICBUTTON_ID_PREV_CHANGE_PAGE   0
-#define ED_GRAPHICBUTTON_ID_NEXT_CHANGE_PAGE   1
-
-#define ED_NUM_GRAPHICBUTTONS                  2
-
-#define ED_GRAPHICBUTTON_ID_CHANGE_FIRST   ED_GRAPHICBUTTON_ID_PREV_CHANGE_PAGE
-#define ED_GRAPHICBUTTON_ID_CHANGE_LAST    ED_GRAPHICBUTTON_ID_NEXT_CHANGE_PAGE
+#define ED_NUM_TEXTBUTTON                      4
 
 /* values for checkbutton gadgets */
 #define ED_CHECKBUTTON_ID_DOUBLE_SPEED         0
@@ -766,7 +726,6 @@ static boolean random_placement_background_restricted = FALSE;
 static boolean stick_element_properties_window = FALSE;
 static boolean custom_element_properties[NUM_ELEMENT_PROPERTIES];
 static boolean custom_element_change_events[NUM_CHANGE_EVENTS];
-static struct ElementChangeInfo custom_element_change;
 static struct ElementInfo custom_element;
 
 static struct
@@ -799,7 +758,7 @@ static struct
     "playfield size:",                 NULL, "width",
   },
   {
-    -1,                                        ED_COUNTER_YPOS(2),
+    ED_SETTINGS_XPOS(0) + 2 * DXSIZE,  ED_COUNTER_YPOS(2),
     MIN_LEV_FIELDY,                    MAX_LEV_FIELDY,
     GADGET_ID_LEVEL_YSIZE_DOWN,                GADGET_ID_LEVEL_YSIZE_UP,
     GADGET_ID_LEVEL_YSIZE_TEXT,                GADGET_ID_LEVEL_XSIZE_UP,
@@ -857,22 +816,6 @@ static struct
     &level.num_yamyam_contents,
     NULL,                              NULL, "number of content areas"
   },
-  {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(0),
-    MIN_ENVELOPE_XSIZE,                        MAX_ENVELOPE_XSIZE,
-    GADGET_ID_ENVELOPE_XSIZE_DOWN,     GADGET_ID_ENVELOPE_XSIZE_UP,
-    GADGET_ID_ENVELOPE_XSIZE_TEXT,     GADGET_ID_NONE,
-    &level.envelope_xsize,
-    NULL,                              NULL, "width",
-  },
-  {
-    -1,                                        ED_SETTINGS_YPOS(0),
-    MIN_ENVELOPE_YSIZE,                        MAX_ENVELOPE_YSIZE,
-    GADGET_ID_ENVELOPE_YSIZE_DOWN,     GADGET_ID_ENVELOPE_YSIZE_UP,
-    GADGET_ID_ENVELOPE_YSIZE_TEXT,     GADGET_ID_ENVELOPE_XSIZE_UP,
-    &level.envelope_ysize,
-    NULL,                              " ", "height",
-  },
 
   /* ---------- element settings: configure (custom elements) ------------- */
 
@@ -882,10 +825,10 @@ static struct
     GADGET_ID_CUSTOM_SCORE_DOWN,       GADGET_ID_CUSTOM_SCORE_UP,
     GADGET_ID_CUSTOM_SCORE_TEXT,       GADGET_ID_NONE,
     &custom_element.collect_score,
-    NULL,                              "score", " "
+    NULL,                              "score", NULL
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(3),
+    ED_SETTINGS_XPOS(13) + 10,         ED_SETTINGS_YPOS(3),
     MIN_COLLECT_COUNT,                 MAX_COLLECT_COUNT,
     GADGET_ID_CUSTOM_GEMCOUNT_DOWN,    GADGET_ID_CUSTOM_GEMCOUNT_UP,
     GADGET_ID_CUSTOM_GEMCOUNT_TEXT,    GADGET_ID_CUSTOM_SCORE_UP,
@@ -901,7 +844,7 @@ static struct
     NULL,                              "push delay", NULL
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(4),
+    ED_COUNT_PUSH_DELAY_RND_XPOS,      ED_SETTINGS_YPOS(4),
     0,                                 999,
     GADGET_ID_PUSH_DELAY_RND_DOWN,     GADGET_ID_PUSH_DELAY_RND_UP,
     GADGET_ID_PUSH_DELAY_RND_TEXT,     GADGET_ID_PUSH_DELAY_FIX_UP,
@@ -917,7 +860,7 @@ static struct
     NULL,                              "move delay", NULL
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(7),
+    ED_COUNT_MOVE_DELAY_RND_XPOS,      ED_SETTINGS_YPOS(7),
     0,                                 999,
     GADGET_ID_MOVE_DELAY_RND_DOWN,     GADGET_ID_MOVE_DELAY_RND_UP,
     GADGET_ID_MOVE_DELAY_RND_TEXT,     GADGET_ID_MOVE_DELAY_FIX_UP,
@@ -932,15 +875,15 @@ static struct
     0,                                 999,
     GADGET_ID_CHANGE_DELAY_FIX_DOWN,   GADGET_ID_CHANGE_DELAY_FIX_UP,
     GADGET_ID_CHANGE_DELAY_FIX_TEXT,   GADGET_ID_NONE,
-    &custom_element_change.delay_fixed,
+    &custom_element.change.delay_fixed,
     NULL,                              "delay", NULL,
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(3),
+    ED_COUNT_CHANGE_DELAY_RND_XPOS+20, ED_SETTINGS_YPOS(3),
     0,                                 999,
     GADGET_ID_CHANGE_DELAY_RND_DOWN,   GADGET_ID_CHANGE_DELAY_RND_UP,
     GADGET_ID_CHANGE_DELAY_RND_TEXT,   GADGET_ID_CHANGE_DELAY_FIX_UP,
-    &custom_element_change.delay_random,
+    &custom_element.change.delay_random,
     NULL,                              "+random", NULL
   },
   {
@@ -948,7 +891,7 @@ static struct
     0,                                 100,
     GADGET_ID_CHANGE_CONT_RND_DOWN,    GADGET_ID_CHANGE_CONT_RND_UP,
     GADGET_ID_CHANGE_CONT_RND_TEXT,    GADGET_ID_NONE,
-    &custom_element_change.random,
+    &custom_element.change.random,
     NULL,                              "use random change:", "(%)"
   },
 };
@@ -959,7 +902,7 @@ static struct
   int gadget_id;
   int size;
   char *value;
-  char *text_above, *infotext;
+  char *infotext;
 } textinput_info[ED_NUM_TEXTINPUT] =
 {
   {
@@ -967,39 +910,21 @@ static struct
     GADGET_ID_LEVEL_NAME,
     MAX_LEVEL_NAME_LEN,
     level.name,
-    "Title:", "Title"
+    "Title"
   },
   {
     ED_SETTINGS_XPOS(0),               ED_COUNTER_YPOS(1),
     GADGET_ID_LEVEL_AUTHOR,
     MAX_LEVEL_AUTHOR_LEN,
     level.author,
-    "Author:", "Author"
+    "Author"
   },
   {
     5 * MINI_TILEX,                    5 * MINI_TILEY - ED_BORDER_SIZE,
     GADGET_ID_ELEMENT_NAME,
     MAX_ELEMENT_NAME_LEN - 2,          /* currently 2 chars less editable */
     custom_element.description,
-    NULL, "Element name"
-  }
-};
-
-static struct
-{
-  int x, y;
-  int gadget_id;
-  int xsize, ysize;
-  char *value;
-  char *text_above, *infotext;
-} textarea_info[ED_NUM_TEXTAREAS] =
-{
-  {
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(2),
-    GADGET_ID_ENVELOPE_INFO,
-    MAX_ENVELOPE_XSIZE, MAX_ENVELOPE_YSIZE,
-    level.envelope,
-    "Envelope Info:", "Envelope Info"
+    "Element name"
   }
 };
 
@@ -1103,7 +1028,7 @@ static struct ValueTextInfo options_consistency[] =
 
 static struct ValueTextInfo options_time_units[] =
 {
-  { FRAMES_PER_SECOND,         "seconds"                       },
+  { 50,                                "seconds"                       },
   { 1,                         "frames"                        },
   { -1,                                NULL                            }
 };
@@ -1146,12 +1071,6 @@ static struct ValueTextInfo options_change_power[] =
   { -1,                                NULL                            }
 };
 
-static char options_change_page_strings[MAX_CHANGE_PAGES][10];
-static struct ValueTextInfo options_change_page[MAX_CHANGE_PAGES + 1] =
-{
-  { -1,                                NULL                            }
-};
-
 static struct
 {
   int x, y;
@@ -1174,7 +1093,7 @@ static struct
     "player can", NULL, "type of access to this field"
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(1),
+    ED_SETTINGS_XPOS(11),              ED_SETTINGS_YPOS(1),
     GADGET_ID_CUSTOM_ACCESS_LAYER,     GADGET_ID_CUSTOM_ACCESS_TYPE,
     -1,
     options_access_layer,
@@ -1214,7 +1133,7 @@ static struct
     "move/fall speed", NULL, "speed of element movement"
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(9),
+    ED_SETTINGS_XPOS(7),               ED_SETTINGS_YPOS(9),
     GADGET_ID_CUSTOM_SMASH_TARGETS,    GADGET_ID_CUSTOM_CAN_SMASH,
     -1,
     options_smash_targets,
@@ -1253,7 +1172,7 @@ static struct
     GADGET_ID_CHANGE_TIME_UNITS,       GADGET_ID_NONE,
     -1,
     options_time_units,
-    &custom_element_change.delay_frames,
+    &custom_element.change.delay_frames,
     "delay time given in", NULL, "delay time units for change"
   },
   {
@@ -1261,7 +1180,7 @@ static struct
     GADGET_ID_CHANGE_PLAYER_ACTION,    GADGET_ID_NONE,
     -1,
     options_change_player_action,
-    &custom_element_change.player_action,
+    &custom_element.change_player_action,
     NULL, "by player", "type of player contact"
   },
   {
@@ -1269,7 +1188,7 @@ static struct
     GADGET_ID_CHANGE_COLLIDE_ACTION,   GADGET_ID_NONE,
     -1,
     options_change_collide_action,
-    &custom_element_change.collide_action,
+    &custom_element.change_collide_action,
     NULL, NULL, "change after impact or smash"
   },
   {
@@ -1277,7 +1196,7 @@ static struct
     GADGET_ID_CHANGE_OTHER_ACTION,     GADGET_ID_NONE,
     -1,
     options_change_other_action,
-    &custom_element_change.other_action,
+    &custom_element.change_other_action,
     NULL, "element:", "type of other element action"
   },
   {
@@ -1285,17 +1204,9 @@ static struct
     GADGET_ID_CHANGE_POWER,            GADGET_ID_NONE,
     -1,
     options_change_power,
-    &custom_element_change.power,
+    &custom_element.change.power,
     "power:", NULL, "power of extended change"
   },
-  {
-    ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(14),
-    GADGET_ID_SELECT_CHANGE_PAGE,      GADGET_ID_NONE,
-    3,
-    options_change_page,
-    &custom_element.current_change_page,
-    NULL, NULL, "element config page"
-  },
 };
 
 static struct
@@ -1304,71 +1215,28 @@ static struct
   int gadget_id;
   int gadget_id_align;
   int size;
-  char *text;
-  char *text_left, *text_right, *infotext;
-} textbutton_info[ED_NUM_TEXTBUTTONS] =
+  char *text, *infotext;
+} textbutton_info[ED_NUM_TEXTBUTTON] =
 {
   {
     ED_SETTINGS_XPOS(0),               ED_COUNTER_YPOS(1),
     GADGET_ID_PROPERTIES_INFO,         GADGET_ID_NONE,
-    11,                                        "Information",                  
-    NULL, NULL,                                "Show information about element"
+    11, "Information",                 "Show information about element"
   },
   {
     ED_SETTINGS_XPOS(0) + 166,         ED_COUNTER_YPOS(1),
     GADGET_ID_PROPERTIES_CONFIG,       GADGET_ID_NONE,
-    11,                                        "Configure",
-    NULL, NULL,                                "Configure element properties"
+    11, "Configure",                   "Configure element properties"
   },
   {
     ED_SETTINGS_XPOS(0) + 332,         ED_COUNTER_YPOS(1),
     GADGET_ID_PROPERTIES_ADVANCED,     GADGET_ID_NONE,
-    11,                                        "Advanced",
-    NULL, NULL,                                "Advanced element configuration"
+    11, "Advanced",                    "Advanced element configuration"
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(13),
+    ED_SETTINGS_XPOS(0) + 262,         ED_SETTINGS_YPOS(13),
     GADGET_ID_SAVE_AS_TEMPLATE,                GADGET_ID_CUSTOM_USE_TEMPLATE,
-    -1,                                        "Save as template",
-    " ", NULL,                         "Save current settings as new template"
-  },
-  {
-    -1,                                        ED_SETTINGS_YPOS(14),
-    GADGET_ID_ADD_CHANGE_PAGE,         GADGET_ID_NEXT_CHANGE_PAGE,
-    -1,                                        "New",
-    " ", NULL,                         "Add new config page"
-  },
-  {
-    -1,                                        ED_SETTINGS_YPOS(14),
-    GADGET_ID_DEL_CHANGE_PAGE,         GADGET_ID_ADD_CHANGE_PAGE,
-    -1,                                        "Delete",
-    NULL, NULL,                                "Delete current config page"
-  },
-};
-
-static struct
-{
-  int gd_x, gd_y;
-  int x, y;
-  int width, height;
-  int gadget_id;
-  int gadget_id_align;
-  char *text_left, *text_right, *infotext;
-} graphicbutton_info[ED_NUM_GRAPHICBUTTONS] =
-{
-  {
-    ED_BUTTON_MINUS_XPOS,              ED_BUTTON_COUNT_YPOS,
-    ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(14),
-    ED_BUTTON_COUNT_XSIZE,             ED_BUTTON_COUNT_YSIZE,
-    GADGET_ID_PREV_CHANGE_PAGE,                GADGET_ID_NONE,
-    NULL, NULL,                                "select previous config page"
-  },
-  {
-    ED_BUTTON_PLUS_XPOS,               ED_BUTTON_COUNT_YPOS,
-    -1,                                        ED_SETTINGS_YPOS(14),
-    ED_BUTTON_COUNT_XSIZE,             ED_BUTTON_COUNT_YSIZE,
-    GADGET_ID_NEXT_CHANGE_PAGE,                GADGET_ID_SELECT_CHANGE_PAGE,
-    NULL, "config page",               "select next config page"
+    -1, "Save as template",            "Save current settings as new template"
   },
 };
 
@@ -1412,10 +1280,10 @@ static struct
   },
   {
     ED_SCROLLBUTTON2_XPOS,  ED_SCROLLBUTTON2_YPOS + 1 * ED_SCROLLBUTTON2_YSIZE,
-    ED_SCROLL2_DOWN_XPOS,   ED_SCROLL2_DOWN_YPOS,
+    ED_SCROLL2_DOWN_XPOS,    ED_SCROLL2_DOWN_YPOS,
     GADGET_ID_SCROLL_LIST_DOWN,
     "scroll element list down ('Page Down')"
-  },
+  }
 };
 
 static struct
@@ -1466,14 +1334,14 @@ static struct
 } radiobutton_info[ED_NUM_RADIOBUTTONS] =
 {
   {
-    -1,                                        ED_COUNTER2_YPOS(8),
+    ED_SETTINGS_XPOS(0) + 160,         ED_COUNTER2_YPOS(8),
     GADGET_ID_RANDOM_PERCENTAGE,       GADGET_ID_LEVEL_RANDOM_UP,
     RADIO_NR_RANDOM_ELEMENTS,
     &random_placement_method,          RANDOM_USE_PERCENTAGE,
     " ", "percentage",                 "use percentage for random elements"
   },
   {
-    -1,                                        ED_COUNTER2_YPOS(8),
+    ED_SETTINGS_XPOS(0) + 340,         ED_COUNTER2_YPOS(8),
     GADGET_ID_RANDOM_QUANTITY,         GADGET_ID_RANDOM_PERCENTAGE,
     RADIO_NR_RANDOM_ELEMENTS,
     &random_placement_method,          RANDOM_USE_QUANTITY,
@@ -1499,7 +1367,7 @@ static struct
     NULL, "double speed movement",     "set movement speed of player"
   },
   {
-    -1,                                        ED_COUNTER_YPOS(6) - MINI_TILEY,
+    ED_SETTINGS_XPOS(0) + 340,         ED_COUNTER_YPOS(6) - MINI_TILEY,
     GADGET_ID_GRAVITY,                 GADGET_ID_DOUBLE_SPEED,
     &level.gravity,
     " ", "gravity",                    "set level gravity"
@@ -1556,7 +1424,7 @@ static struct
     NULL, "can fall",                  "element can fall down"
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(9),
+    ED_SETTINGS_XPOS(6),               ED_SETTINGS_YPOS(9),
     GADGET_ID_CUSTOM_CAN_SMASH,                GADGET_ID_CUSTOM_CAN_FALL,
     &custom_element_properties[EP_CAN_SMASH],
     " ", NULL,                         "element can smash other elements"
@@ -1586,13 +1454,13 @@ static struct
     NULL, "by fire",                   "element can explode by fire/explosion"
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(13),
+    ED_SETTINGS_XPOS(7),               ED_SETTINGS_YPOS(13),
     GADGET_ID_CUSTOM_EXPLODE_SMASH,    GADGET_ID_CUSTOM_EXPLODE_FIRE,
     &custom_element.can_explode_smashed,
     " ", "smashed",                    "element can explode when smashed"
   },
   {
-    -1,                                        ED_SETTINGS_YPOS(13),
+    ED_SETTINGS_XPOS(13),              ED_SETTINGS_YPOS(13),
     GADGET_ID_CUSTOM_EXPLODE_IMPACT,   GADGET_ID_CUSTOM_EXPLODE_SMASH,
     &custom_element.can_explode_impact,
     " ", "impact",                     "element can explode on impact"
@@ -1609,7 +1477,7 @@ static struct
   {
     ED_SETTINGS_XPOS(0),               ED_SETTINGS_YPOS(2),
     GADGET_ID_CUSTOM_CAN_CHANGE,       GADGET_ID_NONE,
-    &custom_element_change.can_change,
+    &custom_element_properties[EP_CAN_CHANGE],
     NULL, "element changes to:",       "element can change to other element"
   },
   {
@@ -1639,25 +1507,25 @@ static struct
   {
     ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(8),
     GADGET_ID_CHANGE_USE_EXPLOSION,    GADGET_ID_NONE,
-    &custom_element_change.explode,
+    &custom_element.change.explode,
     NULL, "explode instead of change", "element explodes instead of change"
   },
   {
     ED_SETTINGS_XPOS(1),               ED_SETTINGS_YPOS(9),
     GADGET_ID_CHANGE_USE_CONTENT,      GADGET_ID_NONE,
-    &custom_element_change.use_content,
+    &custom_element.change.use_content,
     NULL, "use extended change target:","element changes to more elements"
   },
   {
     ED_SETTINGS_XPOS(2),               ED_SETTINGS_YPOS(11),
     GADGET_ID_CHANGE_ONLY_COMPLETE,    GADGET_ID_NONE,
-    &custom_element_change.only_complete,
+    &custom_element.change.only_complete,
     NULL, "only use complete change",  "only use complete extended content"
   },
   {
     ED_SETTINGS_XPOS(2),               ED_SETTINGS_YPOS(12),
     GADGET_ID_CHANGE_USE_RANDOM,       GADGET_ID_NONE,
-    &custom_element_change.use_random_change,
+    &custom_element.change.use_random_change,
     NULL, NULL,                                "use random value for new content"
   },
   {
@@ -1749,7 +1617,7 @@ static struct
   /* ---------- custom graphic --------------------------------------------- */
 
   {
-    -1,                                        ED_AREA_ELEM_CONTENT3_YPOS,
+    ED_AREA_ELEM_CONTENT3_XPOS,                ED_AREA_ELEM_CONTENT3_YPOS,
     1, 1,
     GADGET_ID_CUSTOM_GRAPHIC,          GADGET_ID_CUSTOM_USE_GRAPHIC,
     NULL, NULL,                                NULL
@@ -1767,7 +1635,7 @@ static struct
   /* ---------- custom change target --------------------------------------- */
 
   {
-    -1,                                        ED_AREA_ELEM_CONTENT2_YPOS,
+    ED_AREA_ELEM_CONTENT2_XPOS,                ED_AREA_ELEM_CONTENT2_YPOS,
     1, 1,
     GADGET_ID_CUSTOM_CHANGE_TARGET,    GADGET_ID_CUSTOM_CAN_CHANGE,
     NULL, "after/when:",               NULL
@@ -1785,7 +1653,7 @@ static struct
   /* ---------- custom change trigger (element causing change) ------------- */
 
   {
-    -1,                                        ED_AREA_ELEM_CONTENT5_YPOS,
+    ED_AREA_ELEM_CONTENT5_XPOS,                ED_AREA_ELEM_CONTENT5_YPOS,
     1, 1,
     GADGET_ID_CUSTOM_CHANGE_TRIGGER,   GADGET_ID_CHANGE_OTHER_ACTION,
     NULL, NULL,                                NULL
@@ -1794,7 +1662,7 @@ static struct
   /* ---------- random background (for random painting) -------------------- */
 
   {
-    -1,                                        ED_AREA_RANDOM_BACKGROUND_YPOS,
+    ED_AREA_RANDOM_BACKGROUND_XPOS,    ED_AREA_RANDOM_BACKGROUND_YPOS,
     1, 1,
     GADGET_ID_RANDOM_BACKGROUND,       GADGET_ID_RANDOM_RESTRICTED,
     NULL, NULL,                                NULL
@@ -1840,10 +1708,8 @@ static void CopyLevelToUndoBuffer(int);
 static void HandleDrawingAreas(struct GadgetInfo *);
 static void HandleCounterButtons(struct GadgetInfo *);
 static void HandleTextInputGadgets(struct GadgetInfo *);
-static void HandleTextAreaGadgets(struct GadgetInfo *);
 static void HandleSelectboxGadgets(struct GadgetInfo *);
 static void HandleTextbuttonGadgets(struct GadgetInfo *);
-static void HandleGraphicbuttonGadgets(struct GadgetInfo *);
 static void HandleRadiobuttons(struct GadgetInfo *);
 static void HandleCheckbuttons(struct GadgetInfo *);
 static void HandleControlButtons(struct GadgetInfo *);
@@ -2968,16 +2834,16 @@ static void DrawDrawingArea(int id)
                           el2edimg(custom_element.content[x][y]));
   else if (id == ED_DRAWING_ID_CUSTOM_CHANGE_TARGET)
     DrawMiniGraphicExt(drawto, gi->x, gi->y,
-                      el2edimg(custom_element_change.target_element));
+                      el2edimg(custom_element.change.target_element));
   else if (id == ED_DRAWING_ID_CUSTOM_CHANGE_CONTENT)
     for (y=0; y < 3; y++)
       for (x=0; x < 3; x++)
        DrawMiniGraphicExt(drawto,
                           gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY,
-                          el2edimg(custom_element_change.content[x][y]));
+                          el2edimg(custom_element.change.content[x][y]));
   else if (id == ED_DRAWING_ID_CUSTOM_CHANGE_TRIGGER)
     DrawMiniGraphicExt(drawto, gi->x, gi->y,
-                      el2edimg(custom_element_change.trigger_element));
+                      el2edimg(custom_element.change.trigger_element));
   else if (id >= ED_DRAWING_ID_ELEMENT_CONTENT_0 &&
           id <= ED_DRAWING_ID_ELEMENT_CONTENT_7)
   {
@@ -3355,7 +3221,7 @@ static void CreateCounterButtons()
                          GDI_INFO_TEXT, "enter counter value",
                          GDI_X, x,
                          GDI_Y, y,
-                         GDI_TYPE, GD_TYPE_TEXT_INPUT_NUMERIC,
+                         GDI_TYPE, GD_TYPE_TEXTINPUT_NUMERIC,
                          GDI_NUMBER_VALUE, 0,
                          GDI_NUMBER_MIN, counterbutton_info[i].min_value,
                          GDI_NUMBER_MAX, counterbutton_info[i].max_value,
@@ -3459,7 +3325,7 @@ static void CreateTextInputGadgets()
                      GDI_INFO_TEXT, infotext,
                      GDI_X, SX + textinput_info[i].x,
                      GDI_Y, SY + textinput_info[i].y,
-                     GDI_TYPE, GD_TYPE_TEXT_INPUT_ALPHANUMERIC,
+                     GDI_TYPE, GD_TYPE_TEXTINPUT_ALPHANUMERIC,
                      GDI_TEXT_VALUE, textinput_info[i].value,
                      GDI_TEXT_SIZE, textinput_info[i].size,
                      GDI_TEXT_FONT, FONT_INPUT_1,
@@ -3480,55 +3346,6 @@ static void CreateTextInputGadgets()
   }
 }
 
-static void CreateTextAreaGadgets()
-{
-  int max_infotext_len = getMaxInfoTextLength();
-  int i;
-
-  for (i=0; i<ED_NUM_TEXTAREAS; i++)
-  {
-    Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
-    int gd_x, gd_y;
-    struct GadgetInfo *gi;
-    unsigned long event_mask;
-    char infotext[MAX_OUTPUT_LINESIZE + 1];
-    int id = textarea_info[i].gadget_id;
-    int area_xsize = textarea_info[i].xsize;
-    int area_ysize = textarea_info[i].ysize;
-
-    event_mask = GD_EVENT_TEXT_LEAVING;
-
-    gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
-    gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
-
-    sprintf(infotext, "Enter %s", textarea_info[i].infotext);
-    infotext[max_infotext_len] = '\0';
-
-    gi = CreateGadget(GDI_CUSTOM_ID, id,
-                     GDI_CUSTOM_TYPE_ID, i,
-                     GDI_INFO_TEXT, infotext,
-                     GDI_X, SX + textarea_info[i].x,
-                     GDI_Y, SY + textarea_info[i].y,
-                     GDI_TYPE, GD_TYPE_TEXT_AREA,
-                     GDI_AREA_SIZE, area_xsize, area_ysize,
-                     GDI_TEXT_FONT, FONT_INPUT_1,
-                     GDI_TEXT_FONT_ACTIVE, FONT_INPUT_1_ACTIVE,
-                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x, gd_y,
-                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x, gd_y,
-                     GDI_BORDER_SIZE, ED_BORDER_SIZE, ED_BORDER_SIZE,
-                     GDI_DESIGN_WIDTH, ED_WIN_COUNT_XSIZE,
-                     GDI_EVENT_MASK, event_mask,
-                     GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
-                     GDI_CALLBACK_ACTION, HandleTextAreaGadgets,
-                     GDI_END);
-
-    if (gi == NULL)
-      Error(ERR_EXIT, "cannot create gadget");
-
-    level_editor_gadget[id] = gi;
-  }
-}
-
 static void CreateSelectboxGadgets()
 {
   int max_infotext_len = getMaxInfoTextLength();
@@ -3611,7 +3428,7 @@ static void CreateTextbuttonGadgets()
   int max_infotext_len = getMaxInfoTextLength();
   int i;
 
-  for (i=0; i<ED_NUM_TEXTBUTTONS; i++)
+  for (i=0; i<ED_NUM_TEXTBUTTON; i++)
   {
     Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
     int gd_x1, gd_x2, gd_y1, gd_y2;
@@ -3650,10 +3467,6 @@ static void CreateTextbuttonGadgets()
       x = (right_gadget_border[textbutton_info[i].gadget_id_align] +
           ED_GADGET_TEXT_DISTANCE);
 
-    /* determine horizontal offset for leading text */
-    if (textbutton_info[i].text_left != NULL)
-      x += getTextWidthForGadget(textbutton_info[i].text_left);
-
     gi = CreateGadget(GDI_CUSTOM_ID, id,
                      GDI_CUSTOM_TYPE_ID, i,
                      GDI_INFO_TEXT, infotext,
@@ -3679,64 +3492,6 @@ static void CreateTextbuttonGadgets()
       Error(ERR_EXIT, "cannot create gadget");
 
     level_editor_gadget[id] = gi;
-    right_gadget_border[id] =
-      getRightGadgetBorder(gi, textbutton_info[i].text_right);
-  }
-}
-
-static void CreateGraphicbuttonGadgets()
-{
-  Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
-  struct GadgetInfo *gi;
-  unsigned long event_mask;
-  int i;
-
-  /* create buttons for scrolling of drawing area and element list */
-  for (i=0; i < ED_NUM_GRAPHICBUTTONS; i++)
-  {
-    int id = graphicbutton_info[i].gadget_id;
-    int gd_x1, gd_x2, gd_y1, gd_y2;
-    int x = SX + graphicbutton_info[i].x;
-    int y = SY + graphicbutton_info[i].y;
-
-    event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
-
-    gd_x1 = DOOR_GFX_PAGEX4 + graphicbutton_info[i].gd_x;
-    gd_x2 = DOOR_GFX_PAGEX3 + graphicbutton_info[i].gd_x;
-    gd_y1 = DOOR_GFX_PAGEY1 + graphicbutton_info[i].gd_y;
-    gd_y2 = gd_y1;
-
-    /* determine horizontal position to the right of specified gadget */
-    if (graphicbutton_info[i].gadget_id_align != GADGET_ID_NONE)
-      x = (right_gadget_border[graphicbutton_info[i].gadget_id_align] +
-          ED_GADGET_TEXT_DISTANCE);
-
-    /* determine horizontal offset for leading text */
-    if (graphicbutton_info[i].text_left != NULL)
-      x += getTextWidthForGadget(graphicbutton_info[i].text_left);
-
-    gi = CreateGadget(GDI_CUSTOM_ID, id,
-                     GDI_CUSTOM_TYPE_ID, i,
-                     GDI_INFO_TEXT, graphicbutton_info[i].infotext,
-                     GDI_X, x,
-                     GDI_Y, y,
-                     GDI_WIDTH, graphicbutton_info[i].width,
-                     GDI_HEIGHT, graphicbutton_info[i].height,
-                     GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
-                     GDI_STATE, GD_BUTTON_UNPRESSED,
-                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
-                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
-                     GDI_EVENT_MASK, event_mask,
-                     GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
-                     GDI_CALLBACK_ACTION, HandleGraphicbuttonGadgets,
-                     GDI_END);
-
-    if (gi == NULL)
-      Error(ERR_EXIT, "cannot create gadget");
-
-    level_editor_gadget[id] = gi;
-    right_gadget_border[id] =
-      getRightGadgetBorder(gi, graphicbutton_info[i].text_right);
   }
 }
 
@@ -3952,10 +3707,8 @@ void CreateLevelEditorGadgets()
   CreateCounterButtons();
   CreateRadiobuttonGadgets();
   CreateTextInputGadgets();
-  CreateTextAreaGadgets();
-  CreateSelectboxGadgets();
-  CreateGraphicbuttonGadgets();
   CreateTextbuttonGadgets();
+  CreateSelectboxGadgets();
   CreateDrawingAreas();
 
   game_status = old_game_status;
@@ -4070,35 +3823,25 @@ static void MapDrawingArea(int id)
 static void MapTextInputGadget(int id)
 {
   struct GadgetInfo *gi = level_editor_gadget[textinput_info[id].gadget_id];
+  char infotext[MAX_OUTPUT_LINESIZE + 1];
+  int max_infotext_len = getMaxInfoTextLength();
   int xoffset_above = 0;
   int yoffset_above = -(MINI_TILEX + ED_GADGET_DISTANCE);
-  int x_above = textinput_info[id].x + xoffset_above;
-  int y_above = textinput_info[id].y + yoffset_above;
+  int x = textinput_info[id].x + xoffset_above;
+  int y = textinput_info[id].y + yoffset_above;
 
-  if (textinput_info[id].text_above)
-    DrawTextF(x_above, y_above, FONT_TEXT_1, textinput_info[id].text_above);
+  if (textinput_info[id].infotext)
+  {
+    sprintf(infotext, "%s:", textinput_info[id].infotext);
+    infotext[max_infotext_len] = '\0';
+    DrawTextF(x, y, FONT_TEXT_1, infotext);
+  }
 
   ModifyGadget(gi, GDI_TEXT_VALUE, textinput_info[id].value, GDI_END);
 
   MapGadget(gi);
 }
 
-static void MapTextAreaGadget(int id)
-{
-  struct GadgetInfo *gi = level_editor_gadget[textarea_info[id].gadget_id];
-  int xoffset_above = 0;
-  int yoffset_above = -(MINI_TILEX + ED_GADGET_DISTANCE);
-  int x_above = textarea_info[id].x + xoffset_above;
-  int y_above = textarea_info[id].y + yoffset_above;
-
-  if (textarea_info[id].text_above)
-    DrawTextF(x_above, y_above, FONT_TEXT_1, textarea_info[id].text_above);
-
-  ModifyGadget(gi, GDI_TEXT_VALUE, textarea_info[id].value, GDI_END);
-
-  MapGadget(gi);
-}
-
 static void MapSelectboxGadget(int id)
 {
   struct GadgetInfo *gi = level_editor_gadget[selectbox_info[id].gadget_id];
@@ -4123,42 +3866,6 @@ static void MapSelectboxGadget(int id)
 static void MapTextbuttonGadget(int id)
 {
   struct GadgetInfo *gi = level_editor_gadget[textbutton_info[id].gadget_id];
-  int xoffset_left = getTextWidthForGadget(textbutton_info[id].text_left);
-  int xoffset_right = ED_GADGET_TEXT_DISTANCE;
-  int yoffset = ED_BORDER_SIZE;
-  int x_left = gi->x - xoffset_left;
-  int x_right = gi->x + gi->width + xoffset_right;
-  int y = gi->y + yoffset;
-
-  /* only show button to delete change pages when more than minimum pages */
-  if (id == ED_TEXTBUTTON_ID_DEL_CHANGE_PAGE &&
-      custom_element.num_change_pages == MIN_CHANGE_PAGES)
-    return;
-
-  if (textbutton_info[id].text_left)
-    DrawText(x_left, y, textbutton_info[id].text_left, FONT_TEXT_1);
-
-  if (textbutton_info[id].text_right)
-    DrawText(x_right, y, textbutton_info[id].text_right, FONT_TEXT_1);
-
-  MapGadget(gi);
-}
-
-static void MapGraphicbuttonGadget(int id)
-{
-  struct GadgetInfo *gi= level_editor_gadget[graphicbutton_info[id].gadget_id];
-  int xoffset_left = getTextWidthForGadget(graphicbutton_info[id].text_left);
-  int xoffset_right = ED_GADGET_TEXT_DISTANCE;
-  int yoffset = ED_BORDER_SIZE;
-  int x_left = gi->x - xoffset_left;
-  int x_right = gi->x + gi->width + xoffset_right;
-  int y = gi->y + yoffset;
-
-  if (graphicbutton_info[id].text_left)
-    DrawText(x_left, y, graphicbutton_info[id].text_left, FONT_TEXT_1);
-
-  if (graphicbutton_info[id].text_right)
-    DrawText(x_right, y, graphicbutton_info[id].text_right, FONT_TEXT_1);
 
   MapGadget(gi);
 }
@@ -4166,12 +3873,19 @@ static void MapGraphicbuttonGadget(int id)
 static void MapRadiobuttonGadget(int id)
 {
   struct GadgetInfo *gi = level_editor_gadget[radiobutton_info[id].gadget_id];
+#if 0
+  int xoffset_right = ED_XOFFSET_CHECKBOX;
+  int yoffset_right = ED_BORDER_SIZE;
+  int x = radiobutton_info[id].x + xoffset_right;
+  int y = radiobutton_info[id].y + yoffset_right;
+#else
   int xoffset_left = getTextWidthForGadget(checkbutton_info[id].text_left);
   int xoffset_right = ED_GADGET_TEXT_DISTANCE;
   int yoffset = ED_BORDER_SIZE;
   int x_left = gi->x - xoffset_left;
   int x_right = gi->x + gi->width + xoffset_right;
   int y = gi->y + yoffset;
+#endif
   boolean checked =
     (*radiobutton_info[id].value == radiobutton_info[id].checked_value);
 
@@ -4189,12 +3903,19 @@ static void MapRadiobuttonGadget(int id)
 static void MapCheckbuttonGadget(int id)
 {
   struct GadgetInfo *gi = level_editor_gadget[checkbutton_info[id].gadget_id];
+#if 0
+  int xoffset_right = ED_XOFFSET_CHECKBOX;
+  int yoffset_right = ED_BORDER_SIZE;
+  int x = checkbutton_info[id].x + xoffset_right;
+  int y = checkbutton_info[id].y + yoffset_right;
+#else
   int xoffset_left = getTextWidthForGadget(checkbutton_info[id].text_left);
   int xoffset_right = ED_GADGET_TEXT_DISTANCE;
   int yoffset = ED_BORDER_SIZE;
   int x_left = gi->x - xoffset_left;
   int x_right = gi->x + gi->width + xoffset_right;
   int y = gi->y + yoffset;
+#endif
 
   /* special case needed for "sticky" gadget */
   ModifyGadget(gi, GDI_CHECKED, *checkbutton_info[id].value,
@@ -4320,7 +4041,7 @@ static void CopyPlayfield(short src[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
       dst[x][y] = src[x][y];
 }
 
-static int setSelectboxValue(int selectbox_id, int new_value)
+static int SetSelectboxValue(int selectbox_id, int new_value)
 {
   int new_index_value = 0;
   int i;
@@ -4338,32 +4059,15 @@ static int setSelectboxValue(int selectbox_id, int new_value)
 static void CopyCustomElementPropertiesToEditor(int element)
 {
   int i;
-  int current_change_page = element_info[element].current_change_page;
-
-  /* dynamically (re)build selectbox for selecting change page */
-  for (i=0; i < element_info[element].num_change_pages; i++)
-  {
-    sprintf(options_change_page_strings[i], "%d", i + 1);
-
-    options_change_page[i].value = i;
-    options_change_page[i].text = options_change_page_strings[i];
-  }
-
-  options_change_page[i].value = -1;
-  options_change_page[i].text = NULL;
 
   /* needed here to initialize combined element properties */
   InitElementPropertiesEngine(level.game_version);
 
-  element_info[element].change =
-    &element_info[element].change_page[current_change_page];
-
   custom_element = element_info[element];
-  custom_element_change = *element_info[element].change;
 
   /* needed to initially set selectbox value variables to reliable defaults */
   for (i=0; i < ED_NUM_SELECTBOX; i++)
-    setSelectboxValue(i, *selectbox_info[i].value);
+    SetSelectboxValue(i, *selectbox_info[i].value);
 
   for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
     custom_element_properties[i] = HAS_PROPERTY(element, i);
@@ -4445,22 +4149,22 @@ static void CopyCustomElementPropertiesToEditor(int element)
   /* ---------- element settings: advanced (custom elements) --------------- */
 
   /* set change by player selectbox help value */
-  custom_element_change.player_action =
+  custom_element.change_player_action =
     (HAS_CHANGE_EVENT(element, CE_DROPPED_BY_PLAYER) ? CE_DROPPED_BY_PLAYER :
      HAS_CHANGE_EVENT(element, CE_PUSHED_BY_PLAYER) ? CE_PUSHED_BY_PLAYER :
      HAS_CHANGE_EVENT(element, CE_PRESSED_BY_PLAYER) ? CE_PRESSED_BY_PLAYER :
      HAS_CHANGE_EVENT(element, CE_TOUCHED_BY_PLAYER) ? CE_TOUCHED_BY_PLAYER :
-     custom_element_change.player_action);
+     custom_element.change_player_action);
 
   /* set change by collision selectbox help value */
-  custom_element_change.collide_action =
+  custom_element.change_collide_action =
     (HAS_CHANGE_EVENT(element, CE_SMASHED) ? CE_SMASHED :
      HAS_CHANGE_EVENT(element, CE_IMPACT) ? CE_IMPACT :
      HAS_CHANGE_EVENT(element, CE_COLLISION) ? CE_COLLISION :
-     custom_element_change.collide_action);
+     custom_element.change_collide_action);
 
   /* set change by other element action selectbox help value */
-  custom_element_change.other_action =
+  custom_element.change_other_action =
     (HAS_CHANGE_EVENT(element, CE_OTHER_GETS_DROPPED) ? CE_OTHER_GETS_DROPPED :
      HAS_CHANGE_EVENT(element, CE_OTHER_GETS_COLLECTED) ? CE_OTHER_GETS_COLLECTED :
      HAS_CHANGE_EVENT(element, CE_OTHER_GETS_PUSHED) ? CE_OTHER_GETS_PUSHED :
@@ -4469,7 +4173,7 @@ static void CopyCustomElementPropertiesToEditor(int element)
      HAS_CHANGE_EVENT(element, CE_OTHER_IS_EXPLODING) ? CE_OTHER_IS_EXPLODING :
      HAS_CHANGE_EVENT(element, CE_OTHER_IS_CHANGING) ? CE_OTHER_IS_CHANGING :
      HAS_CHANGE_EVENT(element, CE_OTHER_IS_TOUCHING) ? CE_OTHER_IS_TOUCHING :
-     custom_element_change.other_action);
+     custom_element.change_other_action);
 }
 
 static void CopyCustomElementPropertiesToGame(int element)
@@ -4497,7 +4201,6 @@ static void CopyCustomElementPropertiesToGame(int element)
   }
 
   element_info[element] = custom_element;
-  *element_info[element].change = custom_element_change;
 
   /* ---------- element settings: configure (custom elements) ------------- */
 
@@ -4565,14 +4268,14 @@ static void CopyCustomElementPropertiesToGame(int element)
   custom_element_change_events[CE_PRESSED_BY_PLAYER] = FALSE;
   custom_element_change_events[CE_PUSHED_BY_PLAYER] = FALSE;
   custom_element_change_events[CE_DROPPED_BY_PLAYER] = FALSE;
-  custom_element_change_events[custom_element_change.player_action] =
+  custom_element_change_events[custom_element.change_player_action] =
     custom_element_change_events[CE_BY_PLAYER];
 
   /* set collision change event from checkbox and selectbox */
   custom_element_change_events[CE_COLLISION] = FALSE;
   custom_element_change_events[CE_IMPACT] = FALSE;
   custom_element_change_events[CE_SMASHED] = FALSE;
-  custom_element_change_events[custom_element_change.collide_action] =
+  custom_element_change_events[custom_element.change_collide_action] =
     custom_element_change_events[CE_BY_COLLISION];
 
   /* set other element action change event from checkbox and selectbox */
@@ -4584,7 +4287,7 @@ static void CopyCustomElementPropertiesToGame(int element)
   custom_element_change_events[CE_OTHER_GETS_PUSHED] = FALSE;
   custom_element_change_events[CE_OTHER_GETS_COLLECTED] = FALSE;
   custom_element_change_events[CE_OTHER_GETS_DROPPED] = FALSE;
-  custom_element_change_events[custom_element_change.other_action] =
+  custom_element_change_events[custom_element.change_other_action] =
     custom_element_change_events[CE_BY_OTHER];
 
   for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
@@ -4595,7 +4298,6 @@ static void CopyCustomElementPropertiesToGame(int element)
 
   /* copy change events also to special level editor variable */
   custom_element = element_info[element];
-  custom_element_change = *element_info[element].change;
 }
 
 void DrawLevelEd()
@@ -4769,7 +4471,7 @@ static void ModifyEditorCounter(int counter_id, int new_value)
   ModifyGadget(gi, GDI_NUMBER_VALUE, new_value, GDI_END);
 
   if (counter_value != NULL)
-    *counter_value = gi->textinput.number_value;
+    *counter_value = gi->text.number_value;
 }
 
 static void ModifyEditorCounterLimits(int counter_id, int min, int max)
@@ -4784,7 +4486,7 @@ static void ModifyEditorSelectbox(int selectbox_id, int new_value)
 {
   int gadget_id = selectbox_info[selectbox_id].gadget_id;
   struct GadgetInfo *gi = level_editor_gadget[gadget_id];
-  int new_index_value = setSelectboxValue(selectbox_id, new_value);
+  int new_index_value = SetSelectboxValue(selectbox_id, new_value);
 
   ModifyGadget(gi, GDI_SELECTBOX_INDEX, new_index_value, GDI_END);
 }
@@ -4960,19 +4662,6 @@ static void DrawElementContentAreas()
   DrawText(x, y + 2 * MINI_TILEY, "smashed", FONT_TEXT_1);
 }
 
-static void DrawEnvelopeTextArea()
-{
-  int id = ED_TEXTAREA_ID_ENVELOPE_INFO;
-  struct GadgetInfo *gi = level_editor_gadget[textarea_info[id].gadget_id];
-
-  UnmapGadget(gi);
-  DrawBackground(gi->x, gi->y, gi->width, gi->height);
-
-  ModifyGadget(gi, GDI_AREA_SIZE, level.envelope_xsize, level.envelope_ysize,
-              GDI_END);
-  MapTextAreaGadget(ED_TEXTAREA_ID_ENVELOPE_INFO);
-}
-
 char *getElementDescriptionFilename(int element)
 {
   char *docs_dir = options.docs_directory;
@@ -5380,8 +5069,7 @@ static boolean checkPropertiesConfig()
 
   if (IS_GEM(properties_element) ||
       IS_CUSTOM_ELEMENT(properties_element) ||
-      HAS_CONTENT(properties_element) ||
-      properties_element == EL_ENVELOPE)
+      HAS_CONTENT(properties_element))
     return TRUE;
   else
     for (i=0; elements_with_counter[i].element != -1; i++)
@@ -5433,15 +5121,6 @@ static void DrawPropertiesConfig()
   if (IS_GEM(properties_element))
     MapCheckbuttonGadget(ED_CHECKBUTTON_ID_EM_SLIPPERY_GEMS);
 
-  if (properties_element == EL_ENVELOPE)
-  {
-    /* display counter to choose size of envelope text area */
-    MapCounterButtons(ED_COUNTER_ID_ENVELOPE_XSIZE);
-    MapCounterButtons(ED_COUNTER_ID_ENVELOPE_YSIZE);
-
-    DrawEnvelopeTextArea();
-  }
-
   if (IS_CUSTOM_ELEMENT(properties_element))
   {
     /* draw stickybutton gadget */
@@ -5504,13 +5183,7 @@ static void DrawPropertiesAdvanced()
     MapSelectboxGadget(i);
 
   /* draw textbutton gadgets */
-  for (i=ED_TEXTBUTTON_ID_CHANGE_FIRST; i<=ED_TEXTBUTTON_ID_CHANGE_LAST; i++)
-    MapTextbuttonGadget(i);
-
-  /* draw graphicbutton gadgets */
-  for (i =  ED_GRAPHICBUTTON_ID_CHANGE_FIRST;
-       i <= ED_GRAPHICBUTTON_ID_CHANGE_LAST; i++)
-    MapGraphicbuttonGadget(i);
+  MapTextbuttonGadget(ED_TEXTBUTTON_ID_SAVE_AS_TEMPLATE);
 
   /* draw drawing area gadgets */
   DrawPropertiesAdvancedDrawingAreas();
@@ -6366,19 +6039,19 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
        }
        else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET)
        {
-         custom_element_change.target_element = new_element;
+         custom_element.change.target_element = new_element;
 
          CopyCustomElementPropertiesToGame(properties_element);
        }
        else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
        {
-         custom_element_change.content[sx][sy] = new_element;
+         custom_element.change.content[sx][sy] = new_element;
 
          CopyCustomElementPropertiesToGame(properties_element);
        }
        else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER)
        {
-         custom_element_change.trigger_element = new_element;
+         custom_element.change.trigger_element = new_element;
 
          CopyCustomElementPropertiesToGame(properties_element);
        }
@@ -6493,11 +6166,11 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
       else if (id == GADGET_ID_CUSTOM_CONTENT)
        PickDrawingElement(button, custom_element.content[sx][sy]);
       else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET)
-       PickDrawingElement(button, custom_element_change.target_element);
+       PickDrawingElement(button, custom_element.change.target_element);
       else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
-       PickDrawingElement(button, custom_element_change.content[sx][sy]);
+       PickDrawingElement(button, custom_element.change.content[sx][sy]);
       else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER)
-       PickDrawingElement(button, custom_element_change.trigger_element);
+       PickDrawingElement(button, custom_element.change.trigger_element);
       else if (id == GADGET_ID_RANDOM_BACKGROUND)
        PickDrawingElement(button, random_placement_background_element);
       else if (id >= GADGET_ID_ELEMENT_CONTENT_0 &&
@@ -6543,7 +6216,7 @@ static void HandleCounterButtons(struct GadgetInfo *gi)
   }
 
   if (gadget_id == counterbutton_info[counter_id].gadget_id_text)
-    *counter_value = gi->textinput.number_value;
+    *counter_value = gi->text.number_value;
   else
     ModifyEditorCounter(counter_id, *counter_value + step);
 
@@ -6553,11 +6226,6 @@ static void HandleCounterButtons(struct GadgetInfo *gi)
       DrawElementContentAreas();
       break;
 
-    case ED_COUNTER_ID_ENVELOPE_XSIZE:
-    case ED_COUNTER_ID_ENVELOPE_YSIZE:
-      DrawEnvelopeTextArea();
-      break;
-
     case ED_COUNTER_ID_LEVEL_XSIZE:
     case ED_COUNTER_ID_LEVEL_YSIZE:
       lev_fieldx = level.fieldx;
@@ -6586,7 +6254,7 @@ static void HandleTextInputGadgets(struct GadgetInfo *gi)
 {
   int type_id = gi->custom_type_id;
 
-  strcpy(textinput_info[type_id].value, gi->textinput.value);
+  strcpy(textinput_info[type_id].value, gi->text.value);
 
   if (type_id == ED_TEXTINPUT_ID_ELEMENT_NAME)
   {
@@ -6596,13 +6264,6 @@ static void HandleTextInputGadgets(struct GadgetInfo *gi)
   }
 }
 
-static void HandleTextAreaGadgets(struct GadgetInfo *gi)
-{
-  int type_id = gi->custom_type_id;
-
-  strcpy(textarea_info[type_id].value, gi->textarea.value);
-}
-
 static void HandleSelectboxGadgets(struct GadgetInfo *gi)
 {
   int type_id = gi->custom_type_id;
@@ -6610,26 +6271,19 @@ static void HandleSelectboxGadgets(struct GadgetInfo *gi)
   *selectbox_info[type_id].value =
     selectbox_info[type_id].options[gi->selectbox.index].value;
 
-  if (type_id == ED_SELECTBOX_ID_SELECT_CHANGE_PAGE)
-  {
-    element_info[properties_element].current_change_page = gi->selectbox.index;
-
-    DrawPropertiesWindow();
-  }
-  else if ((type_id >= ED_SELECTBOX_ID_CUSTOM_FIRST &&
-           type_id <= ED_SELECTBOX_ID_CUSTOM_LAST) ||
-          (type_id >= ED_SELECTBOX_ID_CHANGE_FIRST &&
-           type_id <= ED_SELECTBOX_ID_CHANGE_LAST))
+  if ((type_id >= ED_SELECTBOX_ID_CUSTOM_FIRST &&
+       type_id <= ED_SELECTBOX_ID_CUSTOM_LAST) ||
+      (type_id >= ED_SELECTBOX_ID_CHANGE_FIRST &&
+       type_id <= ED_SELECTBOX_ID_CHANGE_LAST))
     CopyCustomElementPropertiesToGame(properties_element);
 }
 
 static void HandleTextbuttonGadgets(struct GadgetInfo *gi)
 {
   int type_id = gi->custom_type_id;
-  int i;
 
-  if (type_id >= ED_TEXTBUTTON_ID_PROPERTIES_FIRST &&
-      type_id <= ED_TEXTBUTTON_ID_PROPERTIES_LAST)
+  if (type_id >= ED_TEXTBUTTON_ID_PROPERTIES_INFO &&
+      type_id <= ED_TEXTBUTTON_ID_PROPERTIES_ADVANCED)
   {
     edit_mode_properties = gi->custom_type_id;
 
@@ -6646,56 +6300,6 @@ static void HandleTextbuttonGadgets(struct GadgetInfo *gi)
     if (new_template)
       Request("Tem- plate saved !", REQ_CONFIRM);
   }
-  else if (type_id == ED_TEXTBUTTON_ID_ADD_CHANGE_PAGE &&
-          custom_element.num_change_pages < MAX_CHANGE_PAGES)
-  {
-    struct ElementInfo *ei = &element_info[properties_element];
-
-    setElementChangePages(ei, ei->num_change_pages + 1);
-
-    /* set new change page to be new current change page */
-    ei->current_change_page = ei->num_change_pages - 1;
-    ei->change = &ei->change_page[ei->current_change_page];
-
-    setElementChangeInfoToDefaults(ei->change);
-
-    DrawPropertiesWindow();
-  }
-  else if (type_id == ED_TEXTBUTTON_ID_DEL_CHANGE_PAGE &&
-          custom_element.num_change_pages > MIN_CHANGE_PAGES)
-  {
-    struct ElementInfo *ei = &element_info[properties_element];
-
-    /* copy all change pages after change page to be deleted */
-    for (i = ei->current_change_page; i < ei->num_change_pages - 1; i++)
-      ei->change_page[i] = ei->change_page[i + 1];
-
-    setElementChangePages(ei, ei->num_change_pages - 1);
-
-    DrawPropertiesWindow();
-  }
-}
-
-static void HandleGraphicbuttonGadgets(struct GadgetInfo *gi)
-{
-  int type_id = gi->custom_type_id;
-
-  if (type_id == ED_GRAPHICBUTTON_ID_PREV_CHANGE_PAGE ||
-      type_id == ED_GRAPHICBUTTON_ID_NEXT_CHANGE_PAGE)
-  {
-    struct ElementInfo *ei = &element_info[properties_element];
-    int step = BUTTON_STEPSIZE(gi->event.button);
-
-    step *= (type_id == ED_GRAPHICBUTTON_ID_PREV_CHANGE_PAGE ? -1 : +1);
-    ei->current_change_page += step;
-
-    if (ei->current_change_page < 0)
-      ei->current_change_page = 0;
-    else if (ei->current_change_page >= ei->num_change_pages)
-      ei->current_change_page = ei->num_change_pages - 1;
-
-    DrawPropertiesWindow();
-  }
 }
 
 static void HandleRadiobuttons(struct GadgetInfo *gi)
@@ -7352,13 +6956,13 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi)
                getElementInfoText(custom_element.content[sx][sy]));
     else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET)
       DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
-               getElementInfoText(custom_element_change.target_element));
+               getElementInfoText(custom_element.change.target_element));
     else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
       DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
-               getElementInfoText(custom_element_change.content[sx][sy]));
+               getElementInfoText(custom_element.change.content[sx][sy]));
     else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER)
       DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
-               getElementInfoText(custom_element_change.trigger_element));
+               getElementInfoText(custom_element.change.trigger_element));
     else if (id == GADGET_ID_RANDOM_BACKGROUND)
       DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2, "%s",
                getElementInfoText(random_placement_background_element));
index db3a432d41aa3623ee0d26ac783343663f6f25c6..e17ef526412bcca6ec178c60922d4d50dacdb657 100644 (file)
 /* level file functions                                                      */
 /* ========================================================================= */
 
-void setElementChangePages(struct ElementInfo *ei, int change_pages)
-{
-  int change_page_size = sizeof(struct ElementChangeInfo);
-
-  ei->num_change_pages = MAX(1, change_pages);
-
-  ei->change_page =
-    checked_realloc(ei->change_page, ei->num_change_pages * change_page_size);
-
-  if (ei->current_change_page >= ei->num_change_pages)
-    ei->current_change_page = ei->num_change_pages - 1;
-
-  ei->change = &ei->change_page[ei->current_change_page];
-}
-
-void setElementChangeInfoToDefaults(struct ElementChangeInfo *change)
-{
-  int x, y;
-
-  change->can_change = FALSE;
-
-  change->events = CE_BITMASK_DEFAULT;
-  change->target_element = EL_EMPTY_SPACE;
-
-  change->delay_fixed = 0;
-  change->delay_random = 0;
-  change->delay_frames = -1;   /* later set to reliable default value */
-
-  change->trigger_element = EL_EMPTY_SPACE;
-
-  change->explode = FALSE;
-  change->use_content = FALSE;
-  change->only_complete = FALSE;
-  change->use_random_change = FALSE;
-  change->random = 0;
-  change->power = CP_NON_DESTRUCTIVE;
-
-  for(x=0; x<3; x++)
-    for(y=0; y<3; y++)
-      change->content[x][y] = EL_EMPTY_SPACE;
-
-  change->player_action = 0;
-  change->collide_action = 0;
-  change->other_action = 0;
-
-  change->pre_change_function = NULL;
-  change->change_function = NULL;
-  change->post_change_function = NULL;
-}
-
 static void setLevelInfoToDefaults(struct LevelInfo *level)
 {
   int i, j, x, y;
@@ -137,10 +87,6 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
   strcpy(level->name, NAMELESS_LEVEL_NAME);
   strcpy(level->author, ANONYMOUS_NAME);
 
-  level->envelope[0] = '\0';
-  level->envelope_xsize = MAX_ENVELOPE_XSIZE;
-  level->envelope_ysize = MAX_ENVELOPE_YSIZE;
-
   for(i=0; i<LEVEL_SCORE_ELEMENTS; i++)
     level->score[i] = 10;
 
@@ -154,17 +100,11 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
   level->field[0][0] = EL_PLAYER_1;
   level->field[STD_LEV_FIELDX - 1][STD_LEV_FIELDY - 1] = EL_EXIT_CLOSED;
 
-  for (i=0; i < MAX_NUM_ELEMENTS; i++)
-  {
-    setElementChangePages(&element_info[i], 1);
-    setElementChangeInfoToDefaults(element_info[i].change);
-  }
-
   for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
   {
     int element = EL_CUSTOM_START + i;
 
-    for(j=0; j < MAX_ELEMENT_NAME_LEN + 1; j++)
+    for(j=0; j<MAX_ELEMENT_NAME_LEN + 1; j++)
       element_info[element].description[j] = '\0';
     if (element_info[element].custom_description != NULL)
       strncpy(element_info[element].description,
@@ -194,19 +134,40 @@ static void setLevelInfoToDefaults(struct LevelInfo *level)
       for(y=0; y<3; y++)
        element_info[element].content[x][y] = EL_EMPTY_SPACE;
 
+    element_info[element].change.events = CE_BITMASK_DEFAULT;
+    element_info[element].change.target_element = EL_EMPTY_SPACE;
+
+    element_info[element].change.delay_fixed = 0;
+    element_info[element].change.delay_random = 0;
+    element_info[element].change.delay_frames = -1;    /* use default */
+
+    element_info[element].change.trigger_element = EL_EMPTY_SPACE;
+
+    element_info[element].change.explode = FALSE;
+    element_info[element].change.use_content = FALSE;
+    element_info[element].change.only_complete = FALSE;
+    element_info[element].change.use_random_change = FALSE;
+    element_info[element].change.random = 0;
+    element_info[element].change.power = CP_NON_DESTRUCTIVE;
+
+    for(x=0; x<3; x++)
+      for(y=0; y<3; y++)
+       element_info[element].change.content[x][y] = EL_EMPTY_SPACE;
+
     element_info[element].access_type = 0;
     element_info[element].access_layer = 0;
     element_info[element].walk_to_action = 0;
     element_info[element].smash_targets = 0;
     element_info[element].deadliness = 0;
     element_info[element].consistency = 0;
+    element_info[element].change_player_action = 0;
+    element_info[element].change_collide_action = 0;
+    element_info[element].change_other_action = 0;
 
     element_info[element].can_explode_by_fire = FALSE;
     element_info[element].can_explode_smashed = FALSE;
     element_info[element].can_explode_impact = FALSE;
 
-    element_info[element].current_change_page = 0;
-
     /* start with no properties at all */
     for (j=0; j < NUM_EP_BITFIELDS; j++)
       Properties[element][j] = EP_BITMASK_DEFAULT;
@@ -493,7 +454,7 @@ static int LoadLevel_CUS2(FILE *file, int chunk_size, struct LevelInfo *level)
     int custom_target_element = getFile16BitBE(file);
 
     if (IS_CUSTOM_ELEMENT(element))
-      element_info[element].change->target_element = custom_target_element;
+      element_info[element].change.target_element = custom_target_element;
     else
       Error(ERR_WARN, "invalid custom element number %d", element);
   }
@@ -554,29 +515,29 @@ static int LoadLevel_CUS3(FILE *file, int chunk_size, struct LevelInfo *level)
        element_info[element].content[x][y] =
          checkLevelElement(getFile16BitBE(file));
 
-    element_info[element].change->events = getFile32BitBE(file);
+    element_info[element].change.events = getFile32BitBE(file);
 
-    element_info[element].change->target_element =
+    element_info[element].change.target_element =
       checkLevelElement(getFile16BitBE(file));
 
-    element_info[element].change->delay_fixed = getFile16BitBE(file);
-    element_info[element].change->delay_random = getFile16BitBE(file);
-    element_info[element].change->delay_frames = getFile16BitBE(file);
+    element_info[element].change.delay_fixed = getFile16BitBE(file);
+    element_info[element].change.delay_random = getFile16BitBE(file);
+    element_info[element].change.delay_frames = getFile16BitBE(file);
 
-    element_info[element].change->trigger_element =
+    element_info[element].change.trigger_element =
       checkLevelElement(getFile16BitBE(file));
 
-    element_info[element].change->explode = getFile8Bit(file);
-    element_info[element].change->use_content = getFile8Bit(file);
-    element_info[element].change->only_complete = getFile8Bit(file);
-    element_info[element].change->use_random_change = getFile8Bit(file);
+    element_info[element].change.explode = getFile8Bit(file);
+    element_info[element].change.use_content = getFile8Bit(file);
+    element_info[element].change.only_complete = getFile8Bit(file);
+    element_info[element].change.use_random_change = getFile8Bit(file);
 
-    element_info[element].change->random = getFile8Bit(file);
-    element_info[element].change->power = getFile8Bit(file);
+    element_info[element].change.random = getFile8Bit(file);
+    element_info[element].change.power = getFile8Bit(file);
 
     for(y=0; y<3; y++)
       for(x=0; x<3; x++)
-       element_info[element].change->content[x][y] =
+       element_info[element].change.content[x][y] =
          checkLevelElement(getFile16BitBE(file));
 
     element_info[element].slippery_type = getFile8Bit(file);
@@ -843,18 +804,6 @@ static void LoadLevel_InitLevel(struct LevelInfo *level, char *filename)
     }
   }
 
-  /* initialize "can_change" field for old levels with only one change page */
-  if (level->game_version <= VERSION_IDENT(3,0,2))
-  {
-    for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
-    {
-      int element = EL_CUSTOM_START + i;
-
-      if (CAN_CHANGE(element))
-       element_info[element].change->can_change = TRUE;
-    }
-  }
-
   /* copy elements to runtime playfield array */
   for(x=0; x<MAX_LEV_FIELDX; x++)
     for(y=0; y<MAX_LEV_FIELDY; y++)
@@ -1066,12 +1015,12 @@ static void SaveLevel_CUS2(FILE *file, struct LevelInfo *level,
   {
     int element = EL_CUSTOM_START + i;
 
-    if (element_info[element].change->target_element != EL_EMPTY_SPACE)
+    if (element_info[element].change.target_element != EL_EMPTY_SPACE)
     {
       if (check < num_changed_custom_elements)
       {
        putFile16BitBE(file, element);
-       putFile16BitBE(file, element_info[element].change->target_element);
+       putFile16BitBE(file, element_info[element].change.target_element);
       }
 
       check++;
@@ -1127,27 +1076,27 @@ static void SaveLevel_CUS3(FILE *file, struct LevelInfo *level,
          for(x=0; x<3; x++)
            putFile16BitBE(file, element_info[element].content[x][y]);
 
-       putFile32BitBE(file, element_info[element].change->events);
+       putFile32BitBE(file, element_info[element].change.events);
 
-       putFile16BitBE(file, element_info[element].change->target_element);
+       putFile16BitBE(file, element_info[element].change.target_element);
 
-       putFile16BitBE(file, element_info[element].change->delay_fixed);
-       putFile16BitBE(file, element_info[element].change->delay_random);
-       putFile16BitBE(file, element_info[element].change->delay_frames);
+       putFile16BitBE(file, element_info[element].change.delay_fixed);
+       putFile16BitBE(file, element_info[element].change.delay_random);
+       putFile16BitBE(file, element_info[element].change.delay_frames);
 
-       putFile16BitBE(file, element_info[element].change->trigger_element);
+       putFile16BitBE(file, element_info[element].change.trigger_element);
 
-       putFile8Bit(file, element_info[element].change->explode);
-       putFile8Bit(file, element_info[element].change->use_content);
-       putFile8Bit(file, element_info[element].change->only_complete);
-       putFile8Bit(file, element_info[element].change->use_random_change);
+       putFile8Bit(file, element_info[element].change.explode);
+       putFile8Bit(file, element_info[element].change.use_content);
+       putFile8Bit(file, element_info[element].change.only_complete);
+       putFile8Bit(file, element_info[element].change.use_random_change);
 
-       putFile8Bit(file, element_info[element].change->random);
-       putFile8Bit(file, element_info[element].change->power);
+       putFile8Bit(file, element_info[element].change.random);
+       putFile8Bit(file, element_info[element].change.power);
 
        for(y=0; y<3; y++)
          for(x=0; x<3; x++)
-           putFile16BitBE(file, element_info[element].change->content[x][y]);
+           putFile16BitBE(file, element_info[element].change.content[x][y]);
 
        putFile8Bit(file, element_info[element].slippery_type);
 
index 1ae371db1f3dee3ce13f253c3bdf77e64f697903..5f5f67dc74cebda330e7159e949724e9e337a4b9 100644 (file)
@@ -16,9 +16,6 @@
 
 #include "main.h"
 
-void setElementChangePages(struct ElementInfo *, int);
-void setElementChangeInfoToDefaults(struct ElementChangeInfo *);
-
 boolean LevelFileExists(int);
 void LoadLevelFromFilename(struct LevelInfo *, char *);
 void LoadLevel(int);
index 0f2aff310c07a1e89555c6d5fa9be3a317eb6a66..7b3017e95a7f2864f62b877f913e4bebceccb933 100644 (file)
@@ -171,6 +171,7 @@ static void TestIfElementTouchesCustomElement(int, int);
 
 static boolean CheckTriggeredElementChange(int, int, int, int);
 static boolean CheckElementChange(int, int, int, int);
+static void ChangeElementNow(int, int, int);
 
 static void PlaySoundLevel(int, int, int);
 static void PlaySoundLevelNearest(int, int, int);
@@ -215,7 +216,7 @@ struct ChangingElementInfo
   void (*post_change_function)(int x, int y);
 };
 
-static struct ChangingElementInfo change_delay_list[] =
+static struct ChangingElementInfo changing_element_list[] =
 {
   {
     EL_NUT_BREAKING,
@@ -414,16 +415,14 @@ collect_count_list[] =
   { EL_UNDEFINED,              0 },
 };
 
+static boolean changing_element[MAX_NUM_ELEMENTS];
 static unsigned long trigger_events[MAX_NUM_ELEMENTS];
 
-#define IS_AUTO_CHANGING(e)    (element_info[e].change_events & \
-                                CH_EVENT_BIT(CE_DELAY))
+#define IS_AUTO_CHANGING(e)    (changing_element[e])
 #define IS_JUST_CHANGING(x, y) (ChangeDelay[x][y] != 0)
 #define IS_CHANGING(x, y)      (IS_AUTO_CHANGING(Feld[x][y]) || \
                                 IS_JUST_CHANGING(x, y))
 
-#define CE_PAGE(e, ce)         (element_info[e].event_page[ce])
-
 
 void GetPlayerConfig()
 {
@@ -743,7 +742,7 @@ void DrawGameDoorValues()
 
 static void InitGameEngine()
 {
-  int i, j, k;
+  int i;
 
   /* set game engine from tape file when re-playing, else from level file */
   game.engine_version = (tape.playing ? tape.engine_version :
@@ -774,82 +773,78 @@ static void InitGameEngine()
   /* ---------- initialize changing elements ------------------------------- */
 
   /* initialize changing elements information */
-  for (i=0; i < MAX_NUM_ELEMENTS; i++)
+  for (i=0; i<MAX_NUM_ELEMENTS; i++)
   {
-    struct ElementInfo *ei = &element_info[i];
-
-    /* this pointer might have been changed in the level editor */
-    ei->change = &ei->change_page[0];
+#if 1
+    element_info[i].change.pre_change_function = NULL;
+    element_info[i].change.change_function = NULL;
+    element_info[i].change.post_change_function = NULL;
 
     if (!IS_CUSTOM_ELEMENT(i))
     {
-      ei->change->target_element = EL_EMPTY_SPACE;
-      ei->change->delay_fixed = 0;
-      ei->change->delay_random = 0;
-      ei->change->delay_frames = 1;
+      element_info[i].change.target_element = EL_EMPTY_SPACE;
+      element_info[i].change.delay_fixed = 0;
+      element_info[i].change.delay_random = 0;
+      element_info[i].change.delay_frames = 1;
     }
 
-    ei->change_events = CE_BITMASK_DEFAULT;
-    for (j=0; j < NUM_CHANGE_EVENTS; j++)
-    {
-      ei->event_page_num[j] = 0;
-      ei->event_page[j] = &ei->change_page[0];
-    }
+    changing_element[i] = FALSE;
+#else
+    changing_element[i].base_element = EL_UNDEFINED;
+    changing_element[i].next_element = EL_UNDEFINED;
+    changing_element[i].change_delay = -1;
+    changing_element[i].pre_change_function = NULL;
+    changing_element[i].change_function = NULL;
+    changing_element[i].post_change_function = NULL;
+#endif
   }
 
   /* add changing elements from pre-defined list */
-  for (i=0; change_delay_list[i].element != EL_UNDEFINED; i++)
+  for (i=0; changing_element_list[i].element != EL_UNDEFINED; i++)
   {
-    struct ChangingElementInfo *ch_delay = &change_delay_list[i];
-    struct ElementInfo *ei = &element_info[ch_delay->element];
-
-    ei->change->target_element       = ch_delay->target_element;
-    ei->change->delay_fixed          = ch_delay->change_delay;
-
-    ei->change->pre_change_function  = ch_delay->pre_change_function;
-    ei->change->change_function      = ch_delay->change_function;
-    ei->change->post_change_function = ch_delay->post_change_function;
-
-    ei->change_events |= CH_EVENT_BIT(CE_DELAY);
-  }
+    int element = changing_element_list[i].element;
+    struct ChangingElementInfo *ce = &changing_element_list[i];
+    struct ElementChangeInfo *change = &element_info[element].change;
 
 #if 1
-  /* add change events from custom element configuration */
-  for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
-  {
-    struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i];
-
-    for (j=0; j < ei->num_change_pages; j++)
-    {
-      if (!ei->change_page[j].can_change)
-       continue;
-
-      for (k=0; k < NUM_CHANGE_EVENTS; k++)
-      {
-       /* only add event page for the first page found with this event */
-       if (ei->change_page[j].events & CH_EVENT_BIT(k) &&
-           !(ei->change_events & CH_EVENT_BIT(k)))
-       {
-         ei->change_events |= CH_EVENT_BIT(k);
-         ei->event_page_num[k] = j;
-         ei->event_page[k] = &ei->change_page[j];
-       }
-      }
-    }
-  }
+    change->target_element       = ce->target_element;
+    change->delay_fixed          = ce->change_delay;
+    change->pre_change_function  = ce->pre_change_function;
+    change->change_function      = ce->change_function;
+    change->post_change_function = ce->post_change_function;
 
+    changing_element[element] = TRUE;
 #else
+    changing_element[element].base_element         = ce->base_element;
+    changing_element[element].next_element         = ce->next_element;
+    changing_element[element].change_delay         = ce->change_delay;
+    changing_element[element].pre_change_function  = ce->pre_change_function;
+    changing_element[element].change_function      = ce->change_function;
+    changing_element[element].post_change_function = ce->post_change_function;
+#endif
+  }
 
-  /* add change events from custom element configuration */
+  /* add changing elements from custom element configuration */
   for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
   {
     int element = EL_CUSTOM_START + i;
+#if 0
+    struct ElementChangeInfo *change = &element_info[element].change;
+#endif
 
     /* only add custom elements that change after fixed/random frame delay */
-    if (CAN_CHANGE(element) && HAS_CHANGE_EVENT(element, CE_DELAY))
-      element_info[element].change_events |= CH_EVENT_BIT(CE_DELAY);
-  }
+    if (!CAN_CHANGE(element) || !HAS_CHANGE_EVENT(element, CE_DELAY))
+      continue;
+
+#if 1
+    changing_element[element] = TRUE;
+#else
+    changing_element[element].base_element = element;
+    changing_element[element].next_element = change->target_element;
+    changing_element[element].change_delay = (change->delay_fixed *
+                                             change->delay_frames);
 #endif
+  }
 
   /* ---------- initialize trigger events ---------------------------------- */
 
@@ -857,32 +852,11 @@ static void InitGameEngine()
   for (i=0; i<MAX_NUM_ELEMENTS; i++)
     trigger_events[i] = EP_BITMASK_DEFAULT;
 
-#if 1
-  /* add trigger events from element change event properties */
-  for (i=0; i<MAX_NUM_ELEMENTS; i++)
-  {
-    struct ElementInfo *ei = &element_info[i];
-
-    for (j=0; j < ei->num_change_pages; j++)
-    {
-      if (!ei->change_page->can_change)
-       continue;
-
-      if (ei->change_page[j].events & CH_EVENT_BIT(CE_BY_OTHER))
-      {
-       int trigger_element = ei->change_page[j].trigger_element;
-
-       trigger_events[trigger_element] |= ei->change_page[j].events;
-      }
-    }
-  }
-#else
   /* add trigger events from element change event properties */
   for (i=0; i<MAX_NUM_ELEMENTS; i++)
     if (HAS_CHANGE_EVENT(i, CE_BY_OTHER))
-      trigger_events[element_info[i].change->trigger_element] |=
-       element_info[i].change->events;
-#endif
+      trigger_events[element_info[i].change.trigger_element] |=
+       element_info[i].change.events;
 
   /* ---------- initialize push delay -------------------------------------- */
 
@@ -1262,19 +1236,16 @@ void InitGame()
 
       if (CAN_CHANGE(element))
       {
-       for (i=0; i < element_info[element].num_change_pages; i++)
-       {
-         content = element_info[element].change_page[i].target_element;
-         is_player = ELEM_IS_PLAYER(content);
+       content = element_info[element].change.target_element;
+       is_player = ELEM_IS_PLAYER(content);
 
-         if (is_player && (found_rating < 3 || element < found_element))
-         {
-           start_x = x;
-           start_y = y;
+       if (is_player && (found_rating < 3 || element < found_element))
+       {
+         start_x = x;
+         start_y = y;
 
-           found_rating = 3;
-           found_element = element;
-         }
+         found_rating = 3;
+         found_element = element;
        }
       }
 
@@ -1295,19 +1266,16 @@ void InitGame()
        if (!CAN_CHANGE(element))
          continue;
 
-       for (i=0; i < element_info[element].num_change_pages; i++)
-       {
-         content = element_info[element].change_page[i].content[xx][yy];
-         is_player = ELEM_IS_PLAYER(content);
+       content = element_info[element].change.content[xx][yy];
+       is_player = ELEM_IS_PLAYER(content);
 
-         if (is_player && (found_rating < 1 || element < found_element))
-         {
-           start_x = x + xx - 1;
-           start_y = y + yy - 1;
+       if (is_player && (found_rating < 1 || element < found_element))
+       {
+         start_x = x + xx - 1;
+         start_y = y + yy - 1;
 
-           found_rating = 1;
-           found_element = element;
-         }
+         found_rating = 1;
+         found_element = element;
        }
       }
     }
@@ -2897,12 +2865,24 @@ void Impact(int x, int y)
     PlaySoundLevel(x, y, SND_PEARL_BREAKING);
     return;
   }
+#if 1
   else if (impact && CheckElementChange(x, y, element, CE_IMPACT))
   {
     PlaySoundLevelElementAction(x, y, element, ACTION_IMPACT);
 
     return;
   }
+#else
+  else if (impact && CAN_CHANGE(element) &&
+          HAS_CHANGE_EVENT(element, CE_IMPACT))
+  {
+    PlaySoundLevelElementAction(x, y, element, ACTION_IMPACT);
+
+    ChangeElementNow(x, y, element);
+
+    return;
+  }
+#endif
 
   if (impact && element == EL_AMOEBA_DROP)
   {
@@ -3034,10 +3014,17 @@ void Impact(int x, int y)
        {
          ToggleLightSwitch(x, y + 1);
        }
+#if 1
        else
        {
          CheckElementChange(x, y + 1, smashed, CE_SMASHED);
        }
+#else
+       else if (CAN_CHANGE(smashed) && HAS_CHANGE_EVENT(smashed, CE_SMASHED))
+       {
+         ChangeElementNow(x, y + 1, smashed);
+       }
+#endif
       }
       else
       {
@@ -5327,7 +5314,7 @@ static void ChangeElementNowExt(int x, int y, int target_element)
 {
   /* check if element under player changes from accessible to unaccessible
      (needed for special case of dropping element which then changes) */
-  if (IS_PLAYER(x, y) && !PLAYER_PROTECTED(x, y) &&
+  if (IS_PLAYER(x, y) &&
       IS_ACCESSIBLE(Feld[x][y]) && !IS_ACCESSIBLE(target_element))
   {
     Bang(x, y);
@@ -5357,12 +5344,26 @@ static void ChangeElementNowExt(int x, int y, int target_element)
     RelocatePlayer(x, y, target_element);
 }
 
-static void ChangeElementNow(int x, int y, int element, int page)
+static void ChangeElementNow(int x, int y, int element)
 {
-  struct ElementChangeInfo *change = &element_info[element].change_page[page];
+  struct ElementChangeInfo *change = &element_info[element].change;
+
+#if 0
+  if (element >= EL_CUSTOM_START + 17 && element <= EL_CUSTOM_START + 39)
+    printf("::: changing... [%d]\n", FrameCounter);
+#endif
+
+#if 0
+  /* prevent CheckTriggeredElementChange() from looping */
+  Changing[x][y] = TRUE;
+#endif
 
   CheckTriggeredElementChange(x, y, Feld[x][y], CE_OTHER_IS_CHANGING);
 
+#if 0
+  Changing[x][y] = FALSE;
+#endif
+
   if (change->explode)
   {
     Bang(x, y);
@@ -5459,21 +5460,42 @@ static void ChangeElementNow(int x, int y, int element, int page)
   }
 }
 
-static void ChangeElement(int x, int y, int page)
+static void ChangeElement(int x, int y)
 {
+#if 1
   int element = MovingOrBlocked2Element(x, y);
-  struct ElementChangeInfo *change = &element_info[element].change_page[page];
+#else
+  int element = Feld[x][y];
+#endif
+  struct ElementChangeInfo *change = &element_info[element].change;
 
   if (ChangeDelay[x][y] == 0)          /* initialize element change */
   {
+#if 1
     ChangeDelay[x][y] = (    change->delay_fixed  * change->delay_frames +
                         RND(change->delay_random * change->delay_frames)) + 1;
+#else
+    ChangeDelay[x][y] = changing_element[element].change_delay + 1;
+
+    if (IS_CUSTOM_ELEMENT(element) && HAS_CHANGE_EVENT(element, CE_DELAY))
+    {
+      int max_random_delay = element_info[element].change.delay_random;
+      int delay_frames = element_info[element].change.delay_frames;
+
+      ChangeDelay[x][y] += RND(max_random_delay * delay_frames);
+    }
+#endif
 
     ResetGfxAnimation(x, y);
     ResetRandomAnimationValue(x, y);
 
+#if 1
     if (change->pre_change_function)
       change->pre_change_function(x, y);
+#else
+    if (changing_element[element].pre_change_function)
+      changing_element[element].pre_change_function(x, y);
+#endif
   }
 
   ChangeDelay[x][y]--;
@@ -5485,11 +5507,20 @@ static void ChangeElement(int x, int y, int page)
     if (IS_ANIMATED(graphic))
       DrawLevelGraphicAnimationIfNeeded(x, y, graphic);
 
+#if 1
     if (change->change_function)
       change->change_function(x, y);
+#else
+    if (changing_element[element].change_function)
+      changing_element[element].change_function(x, y);
+#endif
   }
   else                                 /* finish element change */
   {
+#if 0
+    int next_element = changing_element[element].next_element;
+#endif
+
     if (IS_MOVING(x, y))               /* never change a running system ;-) */
     {
       ChangeDelay[x][y] = 1;           /* try change after next move step */
@@ -5497,17 +5528,27 @@ static void ChangeElement(int x, int y, int page)
       return;
     }
 
-    ChangeElementNow(x, y, element, page);
+#if 1
+    ChangeElementNow(x, y, element);
 
     if (change->post_change_function)
       change->post_change_function(x, y);
+#else
+    if (next_element != EL_UNDEFINED)
+      ChangeElementNow(x, y, next_element);
+    else
+      ChangeElementNow(x, y, element_info[element].change.target_element);
+
+    if (changing_element[element].post_change_function)
+      changing_element[element].post_change_function(x, y);
+#endif
   }
 }
 
 static boolean CheckTriggeredElementChange(int lx, int ly, int trigger_element,
                                           int trigger_event)
 {
-  int i, j, x, y;
+  int i, x, y;
 
   if (!(trigger_events[trigger_element] & CH_EVENT_BIT(trigger_event)))
     return FALSE;
@@ -5516,40 +5557,12 @@ static boolean CheckTriggeredElementChange(int lx, int ly, int trigger_element,
   if (trigger_event == CE_OTHER_IS_CHANGING)
     Changing[lx][ly] = TRUE;
 
-  for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
+  for (i=0; i<MAX_NUM_ELEMENTS; i++)
   {
-    int element = EL_CUSTOM_START + i;
-
-#if 1
-    boolean change_element = FALSE;
-    int page;
-
-    if (!CAN_CHANGE(element) ||
-       !HAS_ANY_CHANGE_EVENT(element, trigger_event))
-      continue;
-
-    for (j=0; j < element_info[element].num_change_pages; j++)
-    {
-      if (element_info[element].change_page[j].trigger_element ==
-         trigger_element)
-      {
-       change_element = TRUE;
-       page = j;
-
-       break;
-      }
-    }
-
-    if (!change_element)
+    if (!CAN_CHANGE(i) || !HAS_CHANGE_EVENT(i, trigger_event) ||
+       element_info[i].change.trigger_element != trigger_element)
       continue;
 
-#else
-    if (!CAN_CHANGE(element) ||
-       !HAS_ANY_CHANGE_EVENT(element, trigger_event) ||
-       element_info[element].change->trigger_element != trigger_element)
-      continue;
-#endif
-
     for (y=0; y<lev_fieldy; y++) for (x=0; x<lev_fieldx; x++)
     {
       if (x == lx && y == ly)  /* do not change trigger element itself */
@@ -5558,10 +5571,10 @@ static boolean CheckTriggeredElementChange(int lx, int ly, int trigger_element,
       if (Changing[x][y])      /* do not change just changing elements */
        continue;
 
-      if (Feld[x][y] == element)
+      if (Feld[x][y] == i)
       {
        ChangeDelay[x][y] = 1;
-       ChangeElement(x, y, page);
+       ChangeElement(x, y);
 
        Changing[x][y] = TRUE;  /* do not change just changed elements */
       }
@@ -5575,28 +5588,20 @@ static boolean CheckTriggeredElementChange(int lx, int ly, int trigger_element,
   return TRUE;
 }
 
-static boolean CheckElementChangeExt(int x, int y, int element,
-                                    int trigger_event, int page)
+static boolean CheckElementChange(int x, int y, int element, int trigger_event)
 {
-  if (!CAN_CHANGE(element) || !HAS_ANY_CHANGE_EVENT(element, trigger_event))
+  if (!CAN_CHANGE(element) || !HAS_CHANGE_EVENT(element, trigger_event))
     return FALSE;
 
   if (Feld[x][y] == EL_BLOCKED)
     Blocked2Moving(x, y, &x, &y);
 
   ChangeDelay[x][y] = 1;
-  ChangeElement(x, y, page);
+  ChangeElement(x, y);
 
   return TRUE;
 }
 
-static boolean CheckElementChange(int x, int y, int element, int trigger_event)
-{
-  int page = element_info[element].event_page_num[trigger_event];
-
-  return CheckElementChangeExt(x, y, element, trigger_event, page);
-}
-
 static void PlayerActions(struct PlayerInfo *player, byte player_action)
 {
   static byte stored_player_action[MAX_PLAYERS];
@@ -5649,7 +5654,13 @@ static void PlayerActions(struct PlayerInfo *player, byte player_action)
     CheckGravityMovement(player);
 
     if (player->MovPos == 0)
+    {
+#if 0
+      printf("Trying... Player frame reset\n");
+#endif
+
       InitPlayerGfxAnimation(player, ACTION_DEFAULT, player->MovDir);
+    }
 
     if (player->MovPos == 0)   /* needed for tape.playing */
       player->is_moving = FALSE;
@@ -5860,7 +5871,7 @@ void GameActions()
     /* this may take place after moving, so 'element' may have changed */
     if (IS_CHANGING(x, y))
     {
-      ChangeElement(x, y, element_info[element].event_page_num[CE_DELAY]);
+      ChangeElement(x, y);
       element = Feld[x][y];
       graphic = el_act_dir2img(element, GfxAction[x][y], MovDir[x][y]);
     }
@@ -6699,9 +6710,8 @@ void TestIfElementTouchesCustomElement(int x, int y)
     { 0, +1 }
   };
   boolean change_center_element = FALSE;
-  int center_element_change_page = 0;
   int center_element = Feld[x][y];
-  int i, j;
+  int i;
 
   if (check_changing)  /* prevent this function from running into a loop */
     return;
@@ -6721,47 +6731,17 @@ void TestIfElementTouchesCustomElement(int x, int y)
 
     /* check for change of center element (but change it only once) */
     if (IS_CUSTOM_ELEMENT(center_element) &&
-       element_info[center_element].change_events & CE_OTHER_IS_TOUCHING &&
-       !change_center_element)
-    {
-      for (j=0; j < element_info[center_element].num_change_pages; j++)
-      {
-       struct ElementChangeInfo *change =
-         &element_info[center_element].change_page[j];
-
-       if (change->events & CE_OTHER_IS_TOUCHING &&
-           change->trigger_element == border_element)
-       {
-         change_center_element = TRUE;
-         center_element_change_page = j;
-
-         break;
-       }
-      }
-    }
+       border_element == element_info[center_element].change.trigger_element)
+      change_center_element = TRUE;
 
     /* check for change of border element */
     if (IS_CUSTOM_ELEMENT(border_element) &&
-       element_info[border_element].change_events & CE_OTHER_IS_TOUCHING)
-    {
-      for (j=0; j < element_info[border_element].num_change_pages; j++)
-      {
-       struct ElementChangeInfo *change =
-         &element_info[border_element].change_page[j];
-
-       if (change->events & CE_OTHER_IS_TOUCHING &&
-           change->trigger_element == center_element)
-       {
-         CheckElementChangeExt(xx,yy, border_element,CE_OTHER_IS_TOUCHING, j);
-         break;
-       }
-      }
-    }
+       center_element == element_info[border_element].change.trigger_element)
+      CheckElementChange(xx, yy, border_element, CE_OTHER_IS_TOUCHING);
   }
 
   if (change_center_element)
-    CheckElementChangeExt(x, y, center_element, CE_OTHER_IS_TOUCHING,
-                         center_element_change_page);
+    CheckElementChange(x, y, center_element, CE_OTHER_IS_TOUCHING);
 
   check_changing = FALSE;
 }
index 86b4ecaec8e64acd0d09510a9fcb2a485dea11a5..c129a676540638525f22d3e1c38facde79b61573 100644 (file)
@@ -2829,12 +2829,6 @@ void InitElementPropertiesEngine(int engine_version)
             element_info[i].token_name,
             element_info[i].crumbled[ACTION_DEFAULT]);
 #endif
-
-    /* ---------- CAN_CHANGE ----------------------------------------------- */
-    SET_PROPERTY(i, EP_CAN_CHANGE, FALSE);     /* default: cannot change */
-    for (j=0; j < element_info[i].num_change_pages; j++)
-      if (element_info[i].change_page[j].can_change)
-       SET_PROPERTY(i, EP_CAN_CHANGE, TRUE);
   }
 
 #if 0
index aacadafad4cfec7fd7d80e42199eae8294ebc91b..7b7041200098360db6ee4b4aadc35decd462da5e 100644 (file)
@@ -105,67 +105,6 @@ static struct GadgetInfo *getGadgetInfoFromMousePosition(int mx, int my)
   return NULL;
 }
 
-static void setTextAreaCursorExt(struct GadgetInfo *gi, boolean set_cursor_pos)
-{
-  char *text = gi->textarea.value;
-  int area_xsize = gi->textarea.xsize;
-  int area_ysize = gi->textarea.ysize;
-  int cursor_position = gi->textarea.cursor_position;
-  int cursor_x = gi->textarea.cursor_x;
-  int cursor_y = gi->textarea.cursor_y;
-  int pos = 0;
-  int x = 0;
-  int y = 0;
-
-  while (*text)
-  {
-    if (set_cursor_pos)                /* x/y => position */
-    {
-      if (y == cursor_y && (x == cursor_x || (x < cursor_x && *text == '\n')))
-       break;
-    }
-    else                       /* position => x/y */
-    {
-      if (pos == cursor_position)
-       break;
-    }
-
-    if (x + 1 >= area_xsize || *text == '\n')
-    {
-      if (y + 1 >= area_ysize)
-       break;
-
-      x = 0;
-      y++;
-    }
-    else
-      x++;
-
-    text++;
-    pos++;
-  }
-
-  gi->textarea.cursor_x = x;
-  gi->textarea.cursor_y = y;
-  gi->textarea.cursor_x_preferred = x;
-  gi->textarea.cursor_position = pos;
-}
-
-static void setTextAreaCursorXY(struct GadgetInfo *gi, int x, int y)
-{
-  gi->textarea.cursor_x = x;
-  gi->textarea.cursor_y = y;
-
-  setTextAreaCursorExt(gi, TRUE);
-}
-
-static void setTextAreaCursorPosition(struct GadgetInfo *gi, int pos)
-{
-  gi->textarea.cursor_position = pos;
-
-  setTextAreaCursorExt(gi, FALSE);
-}
-
 static void default_callback_info(void *ptr)
 {
   return;
@@ -234,8 +173,8 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
       }
       break;
 
-    case GD_TYPE_TEXT_INPUT_ALPHANUMERIC:
-    case GD_TYPE_TEXT_INPUT_NUMERIC:
+    case GD_TYPE_TEXTINPUT_ALPHANUMERIC:
+    case GD_TYPE_TEXTINPUT_NUMERIC:
       {
        int i;
        char cursor_letter;
@@ -251,7 +190,7 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
                               border_x, gi->height, gi->x, gi->y);
 
        /* middle part of gadget */
-       for (i=0; i < gi->textinput.size + 1; i++)
+       for (i=0; i < gi->text.size + 1; i++)
          BlitBitmapOnBackground(gd->bitmap, drawto, gd->x + border_x, gd->y,
                                 font_width, gi->height,
                                 gi->x + border_x + i * font_width, gi->y);
@@ -263,7 +202,7 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
                               gi->x + gi->width - border_x, gi->y);
 
        /* set text value */
-       strcpy(text, gi->textinput.value);
+       strcpy(text, gi->text.value);
        strcat(text, " ");
 
        /* gadget text value */
@@ -271,110 +210,19 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
                    gi->x + border_x, gi->y + border_y, text,
                    font_nr, BLIT_MASKED);
 
-       cursor_letter = gi->textinput.value[gi->textinput.cursor_position];
+       cursor_letter = gi->text.value[gi->text.cursor_position];
        cursor_string[0] = (cursor_letter != '\0' ? cursor_letter : ' ');
        cursor_string[1] = '\0';
 
        /* draw cursor, if active */
        if (pressed)
          DrawTextExt(drawto,
-                     gi->x + border_x +
-                     gi->textinput.cursor_position * font_width,
+                     gi->x + border_x + gi->text.cursor_position * font_width,
                      gi->y + border_y, cursor_string,
                      font_nr, BLIT_INVERSE);
       }
       break;
 
-    case GD_TYPE_TEXT_AREA:
-      {
-       int i;
-       char cursor_letter;
-       char cursor_string[2];
-       int font_nr = (pressed ? gi->font_active : gi->font);
-       int font_width = getFontWidth(font_nr);
-       int font_height = getFontHeight(font_nr);
-       int border_x = gi->border.xsize;
-       int border_y = gi->border.ysize;
-       int gd_height = 2 * border_y + font_height;
-
-       /* top left part of gadget border */
-       BlitBitmapOnBackground(gd->bitmap, drawto, gd->x, gd->y,
-                              border_x, border_y, gi->x, gi->y);
-
-       /* top middle part of gadget border */
-       for (i=0; i < gi->textarea.xsize; i++)
-         BlitBitmapOnBackground(gd->bitmap, drawto, gd->x + border_x, gd->y,
-                                font_width, border_y,
-                                gi->x + border_x + i * font_width, gi->y);
-
-       /* top right part of gadget border */
-       BlitBitmapOnBackground(gd->bitmap, drawto,
-                              gd->x + gi->border.width - border_x, gd->y,
-                              border_x, border_y,
-                              gi->x + gi->width - border_x, gi->y);
-
-       /* left and right part of gadget border for each row */
-       for (i=0; i < gi->textarea.ysize; i++)
-       {
-         BlitBitmapOnBackground(gd->bitmap, drawto, gd->x, gd->y + border_y,
-                                border_x, font_height,
-                                gi->x, gi->y + border_y + i * font_height);
-         BlitBitmapOnBackground(gd->bitmap, drawto,
-                                gd->x + gi->border.width - border_x,
-                                gd->y + border_y,
-                                border_x, font_height,
-                                gi->x + gi->width - border_x,
-                                gi->y + border_y + i * font_height);
-       }
-
-       /* bottom left part of gadget border */
-       BlitBitmapOnBackground(gd->bitmap, drawto,
-                              gd->x, gd->y + gd_height - border_y,
-                              border_x, border_y,
-                              gi->x, gi->y + gi->height - border_y);
-
-       /* bottom middle part of gadget border */
-       for (i=0; i < gi->textarea.xsize; i++)
-         BlitBitmapOnBackground(gd->bitmap, drawto,
-                                gd->x + border_x,
-                                gd->y + gd_height - border_y,
-                                font_width, border_y,
-                                gi->x + border_x + i * font_width,
-                                gi->y + gi->height - border_y);
-
-       /* bottom right part of gadget border */
-       BlitBitmapOnBackground(gd->bitmap, drawto,
-                              gd->x + gi->border.width - border_x,
-                              gd->y + gd_height - border_y,
-                              border_x, border_y,
-                              gi->x + gi->width - border_x,
-                              gi->y + gi->height - border_y);
-
-       ClearRectangleOnBackground(drawto,
-                                  gi->x + border_x,
-                                  gi->y + border_y,
-                                  gi->width - 2 * border_x,
-                                  gi->height - 2 * border_y);
-
-       /* gadget text value */
-       DrawTextToTextArea(gi->x + border_x, gi->y + border_y,
-                          gi->textarea.value, font_nr,
-                          gi->textarea.xsize, gi->textarea.ysize);
-
-       cursor_letter = gi->textarea.value[gi->textarea.cursor_position];
-       cursor_string[0] = (cursor_letter != '\0' ? cursor_letter : ' ');
-       cursor_string[1] = '\0';
-
-       /* draw cursor, if active */
-       if (pressed)
-         DrawTextExt(drawto,
-                     gi->x + border_x + gi->textarea.cursor_x * font_width,
-                     gi->y + border_y + gi->textarea.cursor_y * font_height,
-                     cursor_string,
-                     font_nr, BLIT_INVERSE);
-      }
-      break;
-
     case GD_TYPE_SELECTBOX:
       {
        int i;
@@ -519,10 +367,7 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
          /* selectbox text values */
          for (i=0; i < gi->selectbox.num_values; i++)
          {
-           int mask_mode = BLIT_MASKED;
-
-           strncpy(text, gi->selectbox.options[i].text, gi->selectbox.size);
-           text[gi->selectbox.size] = '\0';
+           int mask_mode;
 
            if (i == gi->selectbox.current_index)
            {
@@ -532,12 +377,18 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
                            gi->selectbox.width - 2 * border_x, font_height,
                            gi->selectbox.inverse_color);
 
-             /* prevent use of cursor graphic by drawing at least two chars */
-             strcat(text, "  ");
-             text[gi->selectbox.size] = '\0';
+             strncpy(text, gi->selectbox.options[i].text, gi->selectbox.size);
+             text[1 + gi->selectbox.size] = '\0';
 
              mask_mode = BLIT_INVERSE;
            }
+           else
+           {
+             strncpy(text, gi->selectbox.options[i].text, gi->selectbox.size);
+             text[gi->selectbox.size] = '\0';
+
+             mask_mode = BLIT_MASKED;
+           }
 
            DrawTextExt(drawto,
                        gi->selectbox.x + border_x,
@@ -757,26 +608,26 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
        break;
 
       case GDI_NUMBER_VALUE:
-       gi->textinput.number_value = va_arg(ap, long);
-       sprintf(gi->textinput.value, "%d", gi->textinput.number_value);
-       gi->textinput.cursor_position = strlen(gi->textinput.value);
+       gi->text.number_value = va_arg(ap, long);
+       sprintf(gi->text.value, "%d", gi->text.number_value);
+       gi->text.cursor_position = strlen(gi->text.value);
        break;
 
       case GDI_NUMBER_MIN:
-       gi->textinput.number_min = va_arg(ap, long);
-       if (gi->textinput.number_value < gi->textinput.number_min)
+       gi->text.number_min = va_arg(ap, long);
+       if (gi->text.number_value < gi->text.number_min)
        {
-         gi->textinput.number_value = gi->textinput.number_min;
-         sprintf(gi->textinput.value, "%d", gi->textinput.number_value);
+         gi->text.number_value = gi->text.number_min;
+         sprintf(gi->text.value, "%d", gi->text.number_value);
        }
        break;
 
       case GDI_NUMBER_MAX:
-       gi->textinput.number_max = va_arg(ap, long);
-       if (gi->textinput.number_value > gi->textinput.number_max)
+       gi->text.number_max = va_arg(ap, long);
+       if (gi->text.number_value > gi->text.number_max)
        {
-         gi->textinput.number_value = gi->textinput.number_max;
-         sprintf(gi->textinput.value, "%d", gi->textinput.number_value);
+         gi->text.number_value = gi->text.number_max;
+         sprintf(gi->text.value, "%d", gi->text.number_value);
        }
        break;
 
@@ -784,16 +635,15 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
        {
          int max_textsize = MAX_GADGET_TEXTSIZE;
 
-         if (gi->textinput.size)
-           max_textsize = MIN(gi->textinput.size, MAX_GADGET_TEXTSIZE - 1);
+         if (gi->text.size)
+           max_textsize = MIN(gi->text.size, MAX_GADGET_TEXTSIZE - 1);
 
-         strncpy(gi->textinput.value, va_arg(ap, char *), max_textsize);
-         gi->textinput.value[max_textsize] = '\0';
-         gi->textinput.cursor_position = strlen(gi->textinput.value);
+         strncpy(gi->text.value, va_arg(ap, char *), max_textsize);
+         gi->text.value[max_textsize] = '\0';
+         gi->text.cursor_position = strlen(gi->text.value);
 
-         /* same tag also used for other gadget definitions */
-         strcpy(gi->textbutton.value, gi->textinput.value);
-         strcpy(gi->textarea.value, gi->textinput.value);
+         /* same tag also used for textbutton definition */
+         strcpy(gi->textbutton.value, gi->text.value);
        }
        break;
 
@@ -802,13 +652,13 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
          int tag_value = va_arg(ap, int);
          int max_textsize = MIN(tag_value, MAX_GADGET_TEXTSIZE - 1);
 
-         gi->textinput.size = max_textsize;
-         gi->textinput.value[max_textsize] = '\0';
+         gi->text.size = max_textsize;
+         gi->text.value[max_textsize] = '\0';
 
-         /* same tag also used for other gadget definitions */
-         strcpy(gi->textbutton.value, gi->textinput.value);
-         gi->textbutton.size = gi->textinput.size;
-         gi->selectbox.size = gi->textinput.size;
+         /* same tag also used for textbutton and selectbox definition */
+         strcpy(gi->textbutton.value, gi->text.value);
+         gi->textbutton.size = gi->text.size;
+         gi->selectbox.size = gi->text.size;
        }
        break;
 
@@ -909,17 +759,6 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
          gi->drawing.item_xsize = gi->width / gi->drawing.area_xsize;
          gi->drawing.item_ysize = gi->height / gi->drawing.area_ysize;
        }
-
-       /* same tag also used for other gadget definitions */
-       gi->textarea.xsize = gi->drawing.area_xsize;
-       gi->textarea.ysize = gi->drawing.area_ysize;
-
-       if (gi->type & GD_TYPE_TEXT_AREA)       /* force recalculation */
-       {
-         gi->width = 0;
-         gi->height = 0;
-       }
-
        break;
 
       case GDI_ITEM_SIZE:
@@ -976,7 +815,7 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
 
   /* adjust gadget values in relation to other gadget values */
 
-  if (gi->type & GD_TYPE_TEXT_INPUT)
+  if (gi->type & GD_TYPE_TEXTINPUT)
   {
     int font_nr = gi->font_active;
     int font_width = getFontWidth(font_nr);
@@ -984,7 +823,7 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
     int border_xsize = gi->border.xsize;
     int border_ysize = gi->border.ysize;
 
-    gi->width  = 2 * border_xsize + (gi->textinput.size + 1) * font_width;
+    gi->width  = 2 * border_xsize + (gi->text.size + 1) * font_width;
     gi->height = 2 * border_ysize + font_height;
   }
 
@@ -1000,7 +839,7 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
     Bitmap *src_bitmap;
     int src_x, src_y;
 
-    gi->width  = 2 * border_xsize + gi->textinput.size*font_width +button_size;
+    gi->width  = 2 * border_xsize + gi->text.size * font_width + button_size;
     gi->height = 2 * border_ysize + font_height;
 
     if (gi->selectbox.options == NULL)
@@ -1031,9 +870,9 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
     gi->selectbox.open = FALSE;
   }
 
-  if (gi->type & GD_TYPE_TEXT_INPUT_NUMERIC)
+  if (gi->type & GD_TYPE_TEXTINPUT_NUMERIC)
   {
-    struct GadgetTextInput *text = &gi->textinput;
+    struct GadgetTextInput *text = &gi->text;
     int value = text->number_value;
 
     text->number_value = (value < text->number_min ? text->number_min :
@@ -1075,26 +914,6 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
     if (gs->item_position == gs->items_max - gs->items_visible)
       gs->position = gs->position_max;
   }
-
-  if (gi->type & GD_TYPE_TEXT_AREA)
-  {
-    int font_nr = gi->font_active;
-    int font_width = getFontWidth(font_nr);
-    int font_height = getFontHeight(font_nr);
-    int border_xsize = gi->border.xsize;
-    int border_ysize = gi->border.ysize;
-
-    if (gi->width == 0 || gi->height == 0)
-    {
-      gi->width  = 2 * border_xsize + gi->textarea.xsize * font_width;
-      gi->height = 2 * border_ysize + gi->textarea.ysize * font_height;
-    }
-    else
-    {
-      gi->textarea.xsize = (gi->width  - 2 * border_xsize) / font_width;
-      gi->textarea.ysize = (gi->height - 2 * border_ysize) / font_height;
-    }
-  }
 }
 
 void ModifyGadget(struct GadgetInfo *gi, int first_tag, ...)
@@ -1165,22 +984,22 @@ void FreeGadget(struct GadgetInfo *gi)
 
 static void CheckRangeOfNumericInputGadget(struct GadgetInfo *gi)
 {
-  if (gi->type != GD_TYPE_TEXT_INPUT_NUMERIC)
+  if (gi->type != GD_TYPE_TEXTINPUT_NUMERIC)
     return;
 
-  gi->textinput.number_value = atoi(gi->textinput.value);
+  gi->text.number_value = atoi(gi->text.value);
 
-  if (gi->textinput.number_value < gi->textinput.number_min)
-    gi->textinput.number_value = gi->textinput.number_min;
-  if (gi->textinput.number_value > gi->textinput.number_max)
-    gi->textinput.number_value = gi->textinput.number_max;
+  if (gi->text.number_value < gi->text.number_min)
+    gi->text.number_value = gi->text.number_min;
+  if (gi->text.number_value > gi->text.number_max)
+    gi->text.number_value = gi->text.number_max;
 
-  sprintf(gi->textinput.value, "%d", gi->textinput.number_value);
+  sprintf(gi->text.value, "%d", gi->text.number_value);
 
-  if (gi->textinput.cursor_position < 0)
-    gi->textinput.cursor_position = 0;
-  else if (gi->textinput.cursor_position > strlen(gi->textinput.value))
-    gi->textinput.cursor_position = strlen(gi->textinput.value);
+  if (gi->text.cursor_position < 0)
+    gi->text.cursor_position = 0;
+  else if (gi->text.cursor_position > strlen(gi->text.value))
+    gi->text.cursor_position = strlen(gi->text.value);
 }
 
 /* global pointer to gadget actually in use (when mouse button pressed) */
@@ -1266,26 +1085,19 @@ void RemapAllGadgets()
   MultiMapGadgets(MULTIMAP_ALL | MULTIMAP_REMAP);
 }
 
-static boolean anyTextInputGadgetActive()
+boolean anyTextInputGadgetActive()
 {
-  return (last_gi && (last_gi->type & GD_TYPE_TEXT_INPUT) && last_gi->mapped);
+  return (last_gi && (last_gi->type & GD_TYPE_TEXTINPUT) && last_gi->mapped);
 }
 
-static boolean anyTextAreaGadgetActive()
-{
-  return (last_gi && (last_gi->type & GD_TYPE_TEXT_AREA) && last_gi->mapped);
-}
-
-static boolean anySelectboxGadgetActive()
+boolean anySelectboxGadgetActive()
 {
   return (last_gi && (last_gi->type & GD_TYPE_SELECTBOX) && last_gi->mapped);
 }
 
 boolean anyTextGadgetActive()
 {
-  return (anyTextInputGadgetActive() ||
-         anyTextAreaGadgetActive() ||
-         anySelectboxGadgetActive());
+  return (anyTextInputGadgetActive() || anySelectboxGadgetActive());
 }
 
 void ClickOnGadget(struct GadgetInfo *gi, int button)
@@ -1348,20 +1160,76 @@ void HandleGadgets(int mx, int my, int button)
   last_mx = mx;
   last_my = my;
 
-  /* if mouse button pressed outside text or selectbox gadget, deactivate it */
-  if (anyTextGadgetActive() &&
-      button != 0 && !motion_status && new_gi != last_gi)
+  /* special treatment for text and number input gadgets */
+  if (anyTextInputGadgetActive() && button != 0 && !motion_status)
   {
-    CheckRangeOfNumericInputGadget(last_gi);   /* in case of numeric gadget */
+    struct GadgetInfo *gi = last_gi;
 
-    DrawGadget(last_gi, DG_UNPRESSED, last_gi->direct_draw);
+    if (new_gi == last_gi)
+    {
+      int old_cursor_position = gi->text.cursor_position;
 
-    last_gi->event.type = GD_EVENT_TEXT_LEAVING;
+      /* if mouse button pressed inside activated text gadget, set cursor */
+      gi->text.cursor_position =
+       (mx - gi->x - gi->border.xsize) / getFontWidth(gi->font);
 
-    if (last_gi->event_mask & GD_EVENT_TEXT_LEAVING)
-      last_gi->callback_action(last_gi);
+      if (gi->text.cursor_position < 0)
+       gi->text.cursor_position = 0;
+      else if (gi->text.cursor_position > strlen(gi->text.value))
+       gi->text.cursor_position = strlen(gi->text.value);
 
-    last_gi = NULL;
+      if (gi->text.cursor_position != old_cursor_position)
+       DrawGadget(gi, DG_PRESSED, gi->direct_draw);
+    }
+    else
+    {
+      /* if mouse button pressed outside text input gadget, deactivate it */
+      CheckRangeOfNumericInputGadget(gi);
+      DrawGadget(gi, DG_UNPRESSED, gi->direct_draw);
+
+      gi->event.type = GD_EVENT_TEXT_LEAVING;
+
+      if (gi->event_mask & GD_EVENT_TEXT_LEAVING)
+       gi->callback_action(gi);
+
+      last_gi = NULL;
+    }
+  }
+
+  /* special treatment for selectbox gadgets */
+  if (anySelectboxGadgetActive() && button != 0 && !motion_status)
+  {
+    struct GadgetInfo *gi = last_gi;
+
+    if (new_gi == last_gi)
+    {
+      int old_index = gi->selectbox.current_index;
+
+      /* if mouse button pressed inside activated selectbox, select value */
+      if (my >= gi->selectbox.y && my < gi->selectbox.y + gi->selectbox.height)
+       gi->selectbox.current_index =
+         (my - gi->selectbox.y - gi->border.ysize) / getFontHeight(gi->font);
+
+      if (gi->selectbox.current_index < 0)
+       gi->selectbox.current_index = 0;
+      else if (gi->selectbox.current_index > gi->selectbox.num_values - 1)
+       gi->selectbox.current_index = gi->selectbox.num_values - 1;
+
+      if (gi->selectbox.current_index != old_index)
+       DrawGadget(gi, DG_PRESSED, gi->direct_draw);
+    }
+    else
+    {
+      /* if mouse button pressed outside selectbox gadget, deactivate it */
+      DrawGadget(gi, DG_UNPRESSED, gi->direct_draw);
+
+      gi->event.type = GD_EVENT_TEXT_LEAVING;
+
+      if (gi->event_mask & GD_EVENT_TEXT_LEAVING)
+       gi->callback_action(gi);
+
+      last_gi = NULL;
+    }
   }
 
   gadget_pressed =
@@ -1410,12 +1278,11 @@ void HandleGadgets(int mx, int my, int button)
   /* if mouse button released, no gadget needs to be handled anymore */
   if (gadget_released)
   {
-    if (last_gi->type & GD_TYPE_SELECTBOX &&
+    if ((last_gi->type & GD_TYPE_SELECTBOX) &&
        (gadget_released_inside_select_line ||
-        gadget_released_off_borders))               /* selectbox stays open */
+        gadget_released_off_borders))              /* selectbox stays open */
       gi->selectbox.stay_open = TRUE;
-    else if (!(last_gi->type & GD_TYPE_TEXT_INPUT ||
-              last_gi->type & GD_TYPE_TEXT_AREA))  /* text input stays open */
+    else if (!(last_gi->type & GD_TYPE_TEXTINPUT))  /* text input stays open */
       last_gi = NULL;
   }
 
@@ -1439,36 +1306,6 @@ void HandleGadgets(int mx, int my, int button)
       if (last_x != gi->event.x || last_y != gi->event.y)
        changed_position = TRUE;
     }
-    else if (gi->type & GD_TYPE_TEXT_INPUT && button != 0 && !motion_status)
-    {
-      int old_cursor_position = gi->textinput.cursor_position;
-
-      /* if mouse button pressed inside activated text gadget, set cursor */
-      gi->textinput.cursor_position =
-       (mx - gi->x - gi->border.xsize) / getFontWidth(gi->font);
-
-      if (gi->textinput.cursor_position < 0)
-       gi->textinput.cursor_position = 0;
-      else if (gi->textinput.cursor_position > strlen(gi->textinput.value))
-       gi->textinput.cursor_position = strlen(gi->textinput.value);
-
-      if (gi->textinput.cursor_position != old_cursor_position)
-       DrawGadget(gi, DG_PRESSED, gi->direct_draw);
-    }
-    else if (gi->type & GD_TYPE_TEXT_AREA && button != 0 && !motion_status)
-    {
-      int old_cursor_position = gi->textarea.cursor_position;
-      int x = (mx - gi->x - gi->border.xsize) / getFontWidth(gi->font);
-      int y = (my - gi->y - gi->border.ysize) / getFontHeight(gi->font);
-
-      x = (x < 0 ? 0 : x >= gi->textarea.xsize ? gi->textarea.xsize - 1 : x);
-      y = (y < 0 ? 0 : y >= gi->textarea.ysize ? gi->textarea.ysize - 1 : y);
-
-      setTextAreaCursorXY(gi, x, y);
-
-      if (gi->textarea.cursor_position != old_cursor_position)
-       DrawGadget(gi, DG_PRESSED, gi->direct_draw);
-    }
     else if (gi->type & GD_TYPE_SELECTBOX)
     {
       int old_index = gi->selectbox.current_index;
@@ -1501,6 +1338,15 @@ void HandleGadgets(int mx, int my, int button)
     {
       last_info_gi->event.type = GD_EVENT_INFO_LEAVING;
       last_info_gi->callback_info(last_info_gi);
+
+#if 0
+      default_callback_info(NULL);
+
+      printf("It seems that we are leaving gadget [%s]!\n",
+            (last_info_gi != NULL &&
+             last_info_gi->info_text != NULL ?
+             last_info_gi->info_text : ""));
+#endif
     }
 
     last_info_gi = new_gi;
@@ -1696,8 +1542,7 @@ void HandleGadgets(int mx, int my, int button)
     }
 
     if (deactivate_gadget &&
-       !(gi->type & GD_TYPE_TEXT_INPUT ||
-         gi->type & GD_TYPE_TEXT_AREA))            /* text input stays open */
+       !(gi->type & GD_TYPE_TEXTINPUT))            /* text input stays open */
       DrawGadget(gi, DG_UNPRESSED, gi->direct_draw);
 
     gi->state = GD_BUTTON_UNPRESSED;
@@ -1724,160 +1569,70 @@ void HandleGadgets(int mx, int my, int button)
     new_gi->state = GD_BUTTON_UNPRESSED;
 }
 
-static void insertCharIntoTextArea(struct GadgetInfo *gi, char c)
-{
-  char text[MAX_GADGET_TEXTSIZE];
-  int cursor_position = gi->textarea.cursor_position;
-
-  if (strlen(gi->textarea.value) == MAX_GADGET_TEXTSIZE) /* no space left */
-    return;
-
-  strcpy(text, gi->textarea.value);
-  strcpy(&gi->textarea.value[cursor_position + 1], &text[cursor_position]);
-  gi->textarea.value[cursor_position] = c;
-
-  setTextAreaCursorPosition(gi, gi->textarea.cursor_position + 1);
-}
-
 void HandleGadgetsKeyInput(Key key)
 {
   struct GadgetInfo *gi = last_gi;
 
   if (gi == NULL || !gi->mapped ||
-      !(gi->type & GD_TYPE_TEXT_INPUT ||
-       gi->type & GD_TYPE_TEXT_AREA ||
-       gi->type & GD_TYPE_SELECTBOX))
+      !((gi->type & GD_TYPE_TEXTINPUT) || (gi->type & GD_TYPE_SELECTBOX)))
     return;
 
   if (key == KSYM_Return)      /* valid for both text input and selectbox */
   {
-    if (gi->type & GD_TYPE_TEXT_INPUT)
+    if (gi->type & GD_TYPE_TEXTINPUT)
       CheckRangeOfNumericInputGadget(gi);
     else if (gi->type & GD_TYPE_SELECTBOX)
       gi->selectbox.index = gi->selectbox.current_index;
 
-    if (gi->type & GD_TYPE_TEXT_AREA)
-    {
-      insertCharIntoTextArea(gi, '\n');
+    DrawGadget(gi, DG_UNPRESSED, gi->direct_draw);
 
-      DrawGadget(gi, DG_PRESSED, gi->direct_draw);
-    }
-    else
-    {
-      DrawGadget(gi, DG_UNPRESSED, gi->direct_draw);
-
-      gi->event.type = GD_EVENT_TEXT_RETURN;
-
-      last_gi = NULL;
-    }
+    gi->event.type = GD_EVENT_TEXT_RETURN;
 
     if (gi->event_mask & GD_EVENT_TEXT_RETURN)
       gi->callback_action(gi);
+
+    last_gi = NULL;
   }
-  else if (gi->type & GD_TYPE_TEXT_INPUT)      /* only valid for text input */
+  else if (gi->type & GD_TYPE_TEXTINPUT)       /* only valid for text input */
   {
     char text[MAX_GADGET_TEXTSIZE];
-    int text_length = strlen(gi->textinput.value);
-    int cursor_pos = gi->textinput.cursor_position;
+    int text_length = strlen(gi->text.value);
+    int cursor_pos = gi->text.cursor_position;
     char letter = getCharFromKey(key);
-    boolean legal_letter = (gi->type == GD_TYPE_TEXT_INPUT_NUMERIC ?
+    boolean legal_letter = (gi->type == GD_TYPE_TEXTINPUT_NUMERIC ?
                            letter >= '0' && letter <= '9' :
                            letter != 0);
 
-    if (legal_letter && text_length < gi->textinput.size)
+    if (legal_letter && text_length < gi->text.size)
     {
-      strcpy(text, gi->textinput.value);
-      strcpy(&gi->textinput.value[cursor_pos + 1], &text[cursor_pos]);
-      gi->textinput.value[cursor_pos] = letter;
-      gi->textinput.cursor_position++;
+      strcpy(text, gi->text.value);
+      strcpy(&gi->text.value[cursor_pos + 1], &text[cursor_pos]);
+      gi->text.value[cursor_pos] = letter;
+      gi->text.cursor_position++;
 
       DrawGadget(gi, DG_PRESSED, gi->direct_draw);
     }
     else if (key == KSYM_Left && cursor_pos > 0)
     {
-      gi->textinput.cursor_position--;
-
+      gi->text.cursor_position--;
       DrawGadget(gi, DG_PRESSED, gi->direct_draw);
     }
     else if (key == KSYM_Right && cursor_pos < text_length)
     {
-      gi->textinput.cursor_position++;
-
+      gi->text.cursor_position++;
       DrawGadget(gi, DG_PRESSED, gi->direct_draw);
     }
     else if (key == KSYM_BackSpace && cursor_pos > 0)
     {
-      strcpy(text, gi->textinput.value);
-      strcpy(&gi->textinput.value[cursor_pos - 1], &text[cursor_pos]);
-      gi->textinput.cursor_position--;
-
+      strcpy(text, gi->text.value);
+      strcpy(&gi->text.value[cursor_pos - 1], &text[cursor_pos]);
+      gi->text.cursor_position--;
       DrawGadget(gi, DG_PRESSED, gi->direct_draw);
     }
     else if (key == KSYM_Delete && cursor_pos < text_length)
     {
-      strcpy(text, gi->textinput.value);
-      strcpy(&gi->textinput.value[cursor_pos], &text[cursor_pos + 1]);
-
-      DrawGadget(gi, DG_PRESSED, gi->direct_draw);
-    }
-  }
-  else if (gi->type & GD_TYPE_TEXT_AREA)       /* only valid for text area */
-  {
-    char text[MAX_GADGET_TEXTSIZE];
-    int text_length = strlen(gi->textarea.value);
-    int area_ysize = gi->textarea.ysize;
-    int cursor_x_pref = gi->textarea.cursor_x_preferred;
-    int cursor_y = gi->textarea.cursor_y;
-    int cursor_pos = gi->textarea.cursor_position;
-    char letter = getCharFromKey(key);
-    boolean legal_letter = (letter != 0);
-
-    if (legal_letter)
-    {
-      insertCharIntoTextArea(gi, letter);
-
-      DrawGadget(gi, DG_PRESSED, gi->direct_draw);
-    }
-    else if (key == KSYM_Left && cursor_pos > 0)
-    {
-      setTextAreaCursorPosition(gi, gi->textarea.cursor_position - 1);
-
-      DrawGadget(gi, DG_PRESSED, gi->direct_draw);
-    }
-    else if (key == KSYM_Right && cursor_pos < text_length)
-    {
-      setTextAreaCursorPosition(gi, gi->textarea.cursor_position + 1);
-
-      DrawGadget(gi, DG_PRESSED, gi->direct_draw);
-    }
-    else if (key == KSYM_Up && cursor_y > 0)
-    {
-      setTextAreaCursorXY(gi, cursor_x_pref, cursor_y - 1);
-      gi->textarea.cursor_x_preferred = cursor_x_pref;
-
-      DrawGadget(gi, DG_PRESSED, gi->direct_draw);
-    }
-    else if (key == KSYM_Down && cursor_y < area_ysize - 1)
-    {
-      setTextAreaCursorXY(gi, cursor_x_pref, cursor_y + 1);
-      gi->textarea.cursor_x_preferred = cursor_x_pref;
-
-      DrawGadget(gi, DG_PRESSED, gi->direct_draw);
-    }
-    else if (key == KSYM_BackSpace && cursor_pos > 0)
-    {
-      strcpy(text, gi->textarea.value);
-      strcpy(&gi->textarea.value[cursor_pos - 1], &text[cursor_pos]);
-
-      setTextAreaCursorPosition(gi, gi->textarea.cursor_position - 1);
-
-      DrawGadget(gi, DG_PRESSED, gi->direct_draw);
-    }
-    else if (key == KSYM_Delete && cursor_pos < text_length)
-    {
-      strcpy(text, gi->textarea.value);
-      strcpy(&gi->textarea.value[cursor_pos], &text[cursor_pos + 1]);
-
+      strcpy(text, gi->text.value);
+      strcpy(&gi->text.value[cursor_pos], &text[cursor_pos + 1]);
       DrawGadget(gi, DG_PRESSED, gi->direct_draw);
     }
   }
@@ -1889,13 +1644,11 @@ void HandleGadgetsKeyInput(Key key)
     if (key == KSYM_Up && index > 0)
     {
       gi->selectbox.current_index--;
-
       DrawGadget(gi, DG_PRESSED, gi->direct_draw);
     }
     else if (key == KSYM_Down && index < num_values - 1)
     {
       gi->selectbox.current_index++;
-
       DrawGadget(gi, DG_PRESSED, gi->direct_draw);
     }
   }
index 160bd611a375311d5372208270f92499be2f21a3..e486a2b7ebe536789da7d7bbd7a97f9d0e69f4e1 100644 (file)
 #define GD_TYPE_CHECK_BUTTON           (1 << 2)
 #define GD_TYPE_RADIO_BUTTON           (1 << 3)
 #define GD_TYPE_DRAWING_AREA           (1 << 4)
-#define GD_TYPE_TEXT_INPUT_ALPHANUMERIC        (1 << 5)
-#define GD_TYPE_TEXT_INPUT_NUMERIC     (1 << 6)
-#define GD_TYPE_TEXT_AREA              (1 << 7)
-#define GD_TYPE_SELECTBOX              (1 << 8)
-#define GD_TYPE_SCROLLBAR_VERTICAL     (1 << 9)
-#define GD_TYPE_SCROLLBAR_HORIZONTAL   (1 << 10)
+#define GD_TYPE_TEXTINPUT_ALPHANUMERIC (1 << 5)
+#define GD_TYPE_TEXTINPUT_NUMERIC      (1 << 6)
+#define GD_TYPE_SELECTBOX              (1 << 7)
+#define GD_TYPE_SCROLLBAR_VERTICAL     (1 << 8)
+#define GD_TYPE_SCROLLBAR_HORIZONTAL   (1 << 9)
 
 #define GD_TYPE_BUTTON                 (GD_TYPE_NORMAL_BUTTON | \
                                         GD_TYPE_TEXT_BUTTON | \
@@ -38,8 +37,8 @@
                                         GD_TYPE_RADIO_BUTTON)
 #define GD_TYPE_SCROLLBAR              (GD_TYPE_SCROLLBAR_VERTICAL | \
                                         GD_TYPE_SCROLLBAR_HORIZONTAL)
-#define GD_TYPE_TEXT_INPUT             (GD_TYPE_TEXT_INPUT_ALPHANUMERIC | \
-                                        GD_TYPE_TEXT_INPUT_NUMERIC)
+#define GD_TYPE_TEXTINPUT              (GD_TYPE_TEXTINPUT_ALPHANUMERIC | \
+                                        GD_TYPE_TEXTINPUT_NUMERIC)
 
 /* gadget events */
 #define GD_EVENT_PRESSED               (1 << 0)
@@ -159,17 +158,6 @@ struct GadgetTextInput
   int size;                            /* maximal size of input text */
 };
 
-struct GadgetTextArea
-{
-  char value[MAX_GADGET_TEXTSIZE];     /* text string in input field */
-  int cursor_position;                 /* actual text cursor position */
-  int cursor_x;                                /* actual x cursor position */
-  int cursor_y;                                /* actual y cursor position */
-  int cursor_x_preferred;              /* "preferred" x cursor position */
-  int size;                            /* maximal size of input text */
-  int xsize, ysize;                    /* size of text area (in chars) */
-};
-
 struct GadgetSelectbox
 {
   struct ValueTextInfo *options;       /* pointer to text/value array */
@@ -228,8 +216,7 @@ struct GadgetInfo
   gadget_function callback_action;     /* function for gadget action */
   struct GadgetDrawingArea drawing;    /* fields for drawing area gadget */
   struct GadgetTextButton textbutton;  /* fields for text button gadget */
-  struct GadgetTextInput textinput;    /* fields for text input gadget */
-  struct GadgetTextArea textarea;      /* fields for text area gadget */
+  struct GadgetTextInput text;         /* fields for text input gadget */
   struct GadgetSelectbox selectbox;    /* fields for selectbox gadget */
   struct GadgetScrollbar scrollbar;    /* fields for scrollbar gadget */
   struct GadgetInfo *next;             /* next list entry */
index d7c264d87115e2609e221102cd3a2f28b89e8123..a4b60302110914df7d3b35640470c9b9ddbc95e3 100644 (file)
@@ -259,9 +259,6 @@ void DrawTextExt(DrawBuffer *dst_bitmap, int dst_x, int dst_y, char *text,
   {
     char c = *text_ptr++;
 
-    if (c == '\n')
-      c = ' ';         /* print space instaed of newline */
-
     getFontCharSource(font_nr, c, &src_bitmap, &src_x, &src_y);
 
     if (mask_mode == BLIT_INVERSE)     /* special mode for text gadgets */
@@ -325,28 +322,3 @@ void DrawTextExt(DrawBuffer *dst_bitmap, int dst_x, int dst_y, char *text,
     dst_x += font_width;
   }
 }
-
-void DrawTextToTextArea(int x, int y, char *text, int font_nr,
-                       int area_xsize, int area_ysize)
-{
-  int area_line = 0;
-  int font_height = getFontWidth(font_nr);
-
-  if (text == NULL)
-    return;
-
-  while (*text && area_line < area_ysize)
-  {
-    char buffer[MAX_OUTPUT_LINESIZE + 1];
-    int i;
-
-    for (i=0; i < area_xsize && *text; i++)
-      if ((buffer[i] = *text++) == '\n')
-       break;
-    buffer[i] = '\0';
-
-    DrawText(x, y + area_line * font_height, buffer, font_nr);
-
-    area_line++;
-  }
-}
index c9c48943b96e9dd33cb635eb74e2d7559468a60b..fd1e8c57d558a1efa501c4b3470183e666930fde 100644 (file)
@@ -66,6 +66,5 @@ void DrawTextF(int, int, int, char *, ...);
 void DrawTextFCentered(int, int, char *, ...);
 void DrawText(int, int, char *, int);
 void DrawTextExt(DrawBuffer *, int, int, char *, int, int);
-void DrawTextToTextArea(int, int, char *, int, int, int);
 
 #endif /* TEXT_H */
index 8a0fca2c30269df31ab100a379625bde365543bf..cab4e71de89b87402187f46a0fdcf9192565ada2 100644 (file)
 #define CE_BITMASK_DEFAULT     0
 
 #define CH_EVENT_BIT(c)                (1 << (c))
-#define CH_EVENT_VAR(e)                (element_info[e].change->events)
-#define CH_ANY_EVENT_VAR(e)    (element_info[e].change_events)
+#define CH_EVENT_VAR(e)                (element_info[e].change.events)
 
 #define HAS_CHANGE_EVENT(e,c)  (IS_CUSTOM_ELEMENT(e) &&                  \
                                 (CH_EVENT_VAR(e) & CH_EVENT_BIT(c)) != 0)
-#define HAS_ANY_CHANGE_EVENT(e,c) (IS_CUSTOM_ELEMENT(e) &&               \
-                                (CH_ANY_EVENT_VAR(e) & CH_EVENT_BIT(c)) != 0)
 #define SET_CHANGE_EVENT(e,c,v)        (IS_CUSTOM_ELEMENT(e) ?                   \
                                 ((v) ?                                   \
                                  (CH_EVENT_VAR(e) |=  CH_EVENT_BIT(c)) : \
 #define IS_LOOP_SOUND(s)       (sound_info[s].loop)
 
 
-/* fundamental game speed values */
-#define GAME_FRAME_DELAY       20      /* frame delay in milliseconds */
-#define FFWD_FRAME_DELAY       10      /* 200% speed for fast forward */
-#define FRAMES_PER_SECOND      (1000 / GAME_FRAME_DELAY)
-#define MICROLEVEL_SCROLL_DELAY        50      /* delay for scrolling micro level */
-#define MICROLEVEL_LABEL_DELAY 250     /* delay for micro level label */
-
 /* boundaries of arrays etc. */
 #define MAX_LEVEL_NAME_LEN     32
 #define MAX_LEVEL_AUTHOR_LEN   32
 #define MAX_ELEMENT_NAME_LEN   32
-#define MAX_TAPELEN            (1000 * FRAMES_PER_SECOND) /* max.time x fps */
+#define MAX_TAPELEN            (1000 * 50)     /* max. time * framerate */
 #define MAX_SCORE_ENTRIES      100
 #define MAX_NUM_AMOEBA         100
 #define MAX_INVENTORY_SIZE     1000
-#define MIN_ENVELOPE_XSIZE     1
-#define MIN_ENVELOPE_YSIZE     1
-#define MAX_ENVELOPE_XSIZE     30
-#define MAX_ENVELOPE_YSIZE     20
-#define MAX_ENVELOPE_TEXT_LEN  (MAX_ENVELOPE_XSIZE * MAX_ENVELOPE_YSIZE)
-#define MIN_CHANGE_PAGES       1
-#define MAX_CHANGE_PAGES       10
 
 /* values for elements with content */
 #define MIN_ELEMENT_CONTENTS   1
 
 #define LEVEL_SCORE_ELEMENTS   16      /* level elements with score */
 
+/* fundamental game speed values */
+#define GAME_FRAME_DELAY       20      /* frame delay in milliseconds */
+#define FFWD_FRAME_DELAY       10      /* 200% speed for fast forward */
+#define FRAMES_PER_SECOND      (1000 / GAME_FRAME_DELAY)
+#define MICROLEVEL_SCROLL_DELAY        50      /* delay for scrolling micro level */
+#define MICROLEVEL_LABEL_DELAY 250     /* delay for micro level label */
+
 /* often used screen positions */
 #define SX                     8
 #define SY                     8
@@ -1122,13 +1112,12 @@ struct LevelInfo
   boolean encoding_16bit_yamyam;       /* yamyam contains 16-bit elements */
   boolean encoding_16bit_amoeba;       /* amoeba contains 16-bit elements */
 
-  int fieldx, fieldy;
+  int fieldx;
+  int fieldy;
   int time;
   int gems_needed;
   char name[MAX_LEVEL_NAME_LEN + 1];
   char author[MAX_LEVEL_AUTHOR_LEN + 1];
-  char envelope[MAX_ENVELOPE_TEXT_LEN + 1];
-  int envelope_xsize, envelope_ysize;
   int score[LEVEL_SCORE_ELEMENTS];
   int yamyam_content[MAX_ELEMENT_CONTENTS][3][3];
   int num_yamyam_contents;
@@ -1146,7 +1135,7 @@ struct LevelInfo
 
   boolean use_custom_template; /* use custom properties from template file */
 
-  boolean no_level_file;       /* set for currently undefined levels */
+  boolean no_level_file;
 };
 
 struct TapeInfo
@@ -1236,8 +1225,6 @@ struct DoorInfo
 
 struct ElementChangeInfo
 {
-  boolean can_change;          /* use or ignore this change info */
-
   unsigned long events;                /* bitfield for change events */
 
   short target_element;                /* target element after change */
@@ -1262,12 +1249,6 @@ struct ElementChangeInfo
   void (*pre_change_function)(int x, int y);
   void (*change_function)(int x, int y);
   void (*post_change_function)(int x, int y);
-
-  /* ---------- internal values used in level editor ---------- */
-
-  int player_action;           /* touched/pressed/pushed by player */
-  int collide_action;          /* collision/impact/smashed */
-  int other_action;            /* various change actions */
 };
 
 struct ElementInfo
@@ -1316,18 +1297,7 @@ struct ElementInfo
 
   int content[3][3];           /* new elements after explosion */
 
-  struct ElementChangeInfo *change_page; /* actual list of change pages */
-  struct ElementChangeInfo *change;     /* pointer to current change page */
-
-  int num_change_pages;                /* actual number of change pages */
-  int current_change_page;     /* currently edited change page */
-
-  /* ---------- internal values used at runtime when playing ---------- */
-
-  unsigned long change_events; /* bitfield for combined change events */
-
-  int event_page_num[NUM_CHANGE_EVENTS]; /* page number for each event */
-  struct ElementChangeInfo *event_page[NUM_CHANGE_EVENTS]; /* page for event */
+  struct ElementChangeInfo change;
 
   /* ---------- internal values used in level editor ---------- */
 
@@ -1337,6 +1307,9 @@ struct ElementInfo
   int smash_targets;           /* can smash player/enemies/everything */
   int deadliness;              /* deadly when running/colliding/touching */
   int consistency;             /* indestructible/can explode */
+  int change_player_action;    /* touched/pressed/pushed by player */
+  int change_collide_action;   /* collision/impact/smashed */
+  int change_other_action;     /* various change actions */
 
   boolean can_explode_by_fire; /* element explodes by fire */
   boolean can_explode_smashed; /* element explodes when smashed */