rnd-20030416-1-src
[rocksndiamonds.git] / src / editor.c
index be1011655149e4e55f290c04942df948074272fc..df3db706e31ba03f7fce6d18943144d25ba9631d 100644 (file)
 #include "game.h"
 #include "tape.h"
 
+
+/*
+  -----------------------------------------------------------------------------
+  screen and artwork graphic pixel position definitions
+  -----------------------------------------------------------------------------
+*/
+
 /* positions in the level editor */
 #define ED_WIN_MB_LEFT_XPOS            6
 #define ED_WIN_MB_LEFT_YPOS            258
 #define ED_WIN_MB_RIGHT_XPOS           78
 #define ED_WIN_MB_RIGHT_YPOS           ED_WIN_MB_LEFT_YPOS
 
-/* other constants for the editor */
-#define ED_SCROLL_NO                   0
-#define ED_SCROLL_LEFT                 1
-#define ED_SCROLL_RIGHT                        2
-#define ED_SCROLL_UP                   4
-#define ED_SCROLL_DOWN                 8
-
-/* screens in the level editor */
-#define ED_MODE_DRAWING                        0
-#define ED_MODE_INFO                   1
-#define ED_MODE_PROPERTIES             2
-
-/* how many steps can be cancelled */
-#define NUM_UNDO_STEPS                 (10 + 1)
-
-/* values for elements with score */
-#define MIN_SCORE                      0
-#define MAX_SCORE                      255
-
 /* values for the control window */
 #define ED_CTRL_BUTTONS_GFX_YPOS       236
 #define ED_CTRL_BUTTONS_ALT_GFX_YPOS   142
 #define ED_COUNTER_YDISTANCE           (3 * MINI_TILEY)
 #define ED_COUNTER_YPOS(n)             (ED_COUNTER_YSTART + \
                                         n * ED_COUNTER_YDISTANCE)
+#define ED_COUNTER_YPOS2(n)            (ED_COUNTER_YSTART + \
+                                        n * ED_COUNTER_YDISTANCE / 2)
 #define ED_COUNTER2_YPOS(n)            (ED_COUNTER_YSTART + \
                                         n * ED_COUNTER_YDISTANCE - 2)
+
 /* standard distances */
 #define ED_BORDER_SIZE                 3
+#define ED_BORDER2_SIZE                        5
 #define ED_GADGET_DISTANCE             2
 
 /* values for element content drawing areas */
 #define ED_AREA_ELEM_CONTENT_XPOS      ( 2 * MINI_TILEX)
 #define ED_AREA_ELEM_CONTENT_YPOS      (22 * MINI_TILEY)
 
+#define ED_AREA_ELEM_CONTENT2_XPOS     ( 2 * MINI_TILEX)
+#define ED_AREA_ELEM_CONTENT2_YPOS     (28 * 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)
 #define ED_STICKYBUTTON_YPOS           (ED_BUTTON_MINUS_YPOS + 66)
 
 /* some positions in the editor control window */
-#define ED_BUTTON_ELEM_XPOS    6
-#define ED_BUTTON_ELEM_YPOS    30
-#define ED_BUTTON_ELEM_XSIZE   22
-#define ED_BUTTON_ELEM_YSIZE   22
-
-/* some values for text input and counter gadgets */
-#define ED_BUTTON_COUNT_YPOS   60
-#define ED_BUTTON_COUNT_XSIZE  20
-#define ED_BUTTON_COUNT_YSIZE  20
-#define ED_WIN_COUNT_XPOS      (2 + ED_BUTTON_COUNT_XSIZE + 2)
-#define ED_WIN_COUNT_YPOS      ED_BUTTON_COUNT_YPOS
-#define ED_WIN_COUNT_XSIZE     52
-#define ED_WIN_COUNT_YSIZE     ED_BUTTON_COUNT_YSIZE
-#define ED_WIN_COUNT2_XPOS     27
-#define ED_WIN_COUNT2_YPOS     3
-#define ED_WIN_COUNT2_XSIZE    46
-#define ED_WIN_COUNT2_YSIZE    ED_BUTTON_COUNT_YSIZE
-
-#define ED_BUTTON_MINUS_XPOS   2
-#define ED_BUTTON_MINUS_YPOS   ED_BUTTON_COUNT_YPOS
-#define ED_BUTTON_MINUS_XSIZE  ED_BUTTON_COUNT_XSIZE
-#define ED_BUTTON_MINUS_YSIZE  ED_BUTTON_COUNT_YSIZE
-#define ED_BUTTON_PLUS_XPOS    (ED_WIN_COUNT_XPOS + ED_WIN_COUNT_XSIZE + 2)
-#define ED_BUTTON_PLUS_YPOS    ED_BUTTON_COUNT_YPOS
-#define ED_BUTTON_PLUS_XSIZE   ED_BUTTON_COUNT_XSIZE
-#define ED_BUTTON_PLUS_YSIZE   ED_BUTTON_COUNT_YSIZE
-
-/* editor gadget identifiers */
+#define ED_BUTTON_ELEM_XPOS            6
+#define ED_BUTTON_ELEM_YPOS            30
+#define ED_BUTTON_ELEM_XSIZE           22
+#define ED_BUTTON_ELEM_YSIZE           22
+
+/* some values for text input, selectbox and counter gadgets */
+#define ED_BUTTON_COUNT_YPOS           60
+#define ED_BUTTON_COUNT_XSIZE          20
+#define ED_BUTTON_COUNT_YSIZE          20
+#define ED_WIN_COUNT_XPOS              (2 + ED_BUTTON_COUNT_XSIZE + 2)
+#define ED_WIN_COUNT_YPOS              ED_BUTTON_COUNT_YPOS
+#define ED_WIN_COUNT_XSIZE             52
+#define ED_WIN_COUNT_YSIZE             ED_BUTTON_COUNT_YSIZE
+#define ED_WIN_COUNT2_XPOS             27
+#define ED_WIN_COUNT2_YPOS             3
+#define ED_WIN_COUNT2_XSIZE            46
+#define ED_WIN_COUNT2_YSIZE            ED_BUTTON_COUNT_YSIZE
+
+#define ED_BUTTON_MINUS_XPOS           2
+#define ED_BUTTON_MINUS_YPOS           ED_BUTTON_COUNT_YPOS
+#define ED_BUTTON_MINUS_XSIZE          ED_BUTTON_COUNT_XSIZE
+#define ED_BUTTON_MINUS_YSIZE          ED_BUTTON_COUNT_YSIZE
+#define ED_BUTTON_PLUS_XPOS            (ED_WIN_COUNT_XPOS + \
+                                        ED_WIN_COUNT_XSIZE + 2)
+#define ED_BUTTON_PLUS_YPOS            ED_BUTTON_COUNT_YPOS
+#define ED_BUTTON_PLUS_XSIZE           ED_BUTTON_COUNT_XSIZE
+#define ED_BUTTON_PLUS_YSIZE           ED_BUTTON_COUNT_YSIZE
+
+#define ED_SELECTBOX_XPOS              ED_WIN_COUNT_XPOS
+#define ED_SELECTBOX_YPOS              (ED_WIN_COUNT_YPOS + \
+                                        2 + ED_WIN_COUNT_YSIZE)
+#define ED_SELECTBOX_XSIZE             ED_WIN_COUNT_XSIZE
+#define ED_SELECTBOX_YSIZE             ED_WIN_COUNT_YSIZE
+
+#define ED_TEXTBUTTON_XPOS             ED_WIN_COUNT_XPOS
+#define ED_TEXTBUTTON_YPOS             (ED_WIN_COUNT_YPOS + \
+                                        2 * (2 + ED_WIN_COUNT_YSIZE))
+#define ED_TEXTBUTTON_INACTIVE_YPOS    (ED_WIN_COUNT_YPOS + \
+                                        3 * (2 + ED_WIN_COUNT_YSIZE))
+#define ED_TEXTBUTTON_XSIZE            ED_WIN_COUNT_XSIZE
+#define ED_TEXTBUTTON_YSIZE            ED_WIN_COUNT_YSIZE
+
+/* values for ClearEditorGadgetInfoText() and HandleGadgetInfoText() */
+#define INFOTEXT_XPOS                  SX
+#define INFOTEXT_YPOS                  (SY + SYSIZE - MINI_TILEX + 2)
+#define INFOTEXT_XSIZE                 SXSIZE
+#define INFOTEXT_YSIZE                 MINI_TILEX
+
+
+/*
+  -----------------------------------------------------------------------------
+  editor gadget definitions
+  -----------------------------------------------------------------------------
+*/
 
 /* drawing toolbox buttons */
 #define GADGET_ID_NONE                 -1
-#define GADGET_ID_SINGLE_ITEMS         0
-#define GADGET_ID_CONNECTED_ITEMS      1
-#define GADGET_ID_LINE                 2
-#define GADGET_ID_ARC                  3
-#define GADGET_ID_RECTANGLE            4
-#define GADGET_ID_FILLED_BOX           5
-#define GADGET_ID_WRAP_UP              6
-#define GADGET_ID_TEXT                 7
-#define GADGET_ID_FLOOD_FILL           8
-#define GADGET_ID_WRAP_LEFT            9
-#define GADGET_ID_PROPERTIES           10
-#define GADGET_ID_WRAP_RIGHT           11
-#define GADGET_ID_RANDOM_PLACEMENT     12
-#define GADGET_ID_GRAB_BRUSH           13
-#define GADGET_ID_WRAP_DOWN            14
-#define GADGET_ID_PICK_ELEMENT         15
-#define GADGET_ID_UNDO                 16
-#define GADGET_ID_INFO                 17
-#define GADGET_ID_SAVE                 18
-#define GADGET_ID_CLEAR                        19
-#define GADGET_ID_TEST                 20
-#define GADGET_ID_EXIT                 21
+#define GADGET_ID_TOOLBOX_FIRST                0
+
+#define GADGET_ID_SINGLE_ITEMS         (GADGET_ID_TOOLBOX_FIRST + 0)
+#define GADGET_ID_CONNECTED_ITEMS      (GADGET_ID_TOOLBOX_FIRST + 1)
+#define GADGET_ID_LINE                 (GADGET_ID_TOOLBOX_FIRST + 2)
+#define GADGET_ID_ARC                  (GADGET_ID_TOOLBOX_FIRST + 3)
+#define GADGET_ID_RECTANGLE            (GADGET_ID_TOOLBOX_FIRST + 4)
+#define GADGET_ID_FILLED_BOX           (GADGET_ID_TOOLBOX_FIRST + 5)
+#define GADGET_ID_WRAP_UP              (GADGET_ID_TOOLBOX_FIRST + 6)
+#define GADGET_ID_TEXT                 (GADGET_ID_TOOLBOX_FIRST + 7)
+#define GADGET_ID_FLOOD_FILL           (GADGET_ID_TOOLBOX_FIRST + 8)
+#define GADGET_ID_WRAP_LEFT            (GADGET_ID_TOOLBOX_FIRST + 9)
+#define GADGET_ID_PROPERTIES           (GADGET_ID_TOOLBOX_FIRST + 10)
+#define GADGET_ID_WRAP_RIGHT           (GADGET_ID_TOOLBOX_FIRST + 11)
+#define GADGET_ID_RANDOM_PLACEMENT     (GADGET_ID_TOOLBOX_FIRST + 12)
+#define GADGET_ID_GRAB_BRUSH           (GADGET_ID_TOOLBOX_FIRST + 13)
+#define GADGET_ID_WRAP_DOWN            (GADGET_ID_TOOLBOX_FIRST + 14)
+#define GADGET_ID_PICK_ELEMENT         (GADGET_ID_TOOLBOX_FIRST + 15)
+#define GADGET_ID_UNDO                 (GADGET_ID_TOOLBOX_FIRST + 16)
+#define GADGET_ID_INFO                 (GADGET_ID_TOOLBOX_FIRST + 17)
+#define GADGET_ID_SAVE                 (GADGET_ID_TOOLBOX_FIRST + 18)
+#define GADGET_ID_CLEAR                        (GADGET_ID_TOOLBOX_FIRST + 19)
+#define GADGET_ID_TEST                 (GADGET_ID_TOOLBOX_FIRST + 20)
+#define GADGET_ID_EXIT                 (GADGET_ID_TOOLBOX_FIRST + 21)
 
 /* counter button identifiers */
-#define GADGET_ID_ELEM_SCORE_DOWN      22
-#define GADGET_ID_ELEM_SCORE_TEXT      23
-#define GADGET_ID_ELEM_SCORE_UP                24
-#define GADGET_ID_ELEM_CONTENT_DOWN    25
-#define GADGET_ID_ELEM_CONTENT_TEXT    26
-#define GADGET_ID_ELEM_CONTENT_UP      27
-#define GADGET_ID_LEVEL_XSIZE_DOWN     28
-#define GADGET_ID_LEVEL_XSIZE_TEXT     29
-#define GADGET_ID_LEVEL_XSIZE_UP       30
-#define GADGET_ID_LEVEL_YSIZE_DOWN     31
-#define GADGET_ID_LEVEL_YSIZE_TEXT     32
-#define GADGET_ID_LEVEL_YSIZE_UP       33
-#define GADGET_ID_LEVEL_RANDOM_DOWN    34
-#define GADGET_ID_LEVEL_RANDOM_TEXT    35
-#define GADGET_ID_LEVEL_RANDOM_UP      36
-#define GADGET_ID_LEVEL_COLLECT_DOWN   37
-#define GADGET_ID_LEVEL_COLLECT_TEXT   38
-#define GADGET_ID_LEVEL_COLLECT_UP     39
-#define GADGET_ID_LEVEL_TIMELIMIT_DOWN 40
-#define GADGET_ID_LEVEL_TIMELIMIT_TEXT 41
-#define GADGET_ID_LEVEL_TIMELIMIT_UP   42
-#define GADGET_ID_LEVEL_TIMESCORE_DOWN 43
-#define GADGET_ID_LEVEL_TIMESCORE_TEXT 44
-#define GADGET_ID_LEVEL_TIMESCORE_UP   45
-#define GADGET_ID_SELECT_LEVEL_DOWN    46
-#define GADGET_ID_SELECT_LEVEL_TEXT    47
-#define GADGET_ID_SELECT_LEVEL_UP      48
+#define GADGET_ID_COUNTER_FIRST                (GADGET_ID_TOOLBOX_FIRST + 22)
+
+#define GADGET_ID_ELEM_SCORE_DOWN      (GADGET_ID_COUNTER_FIRST + 0)
+#define GADGET_ID_ELEM_SCORE_TEXT      (GADGET_ID_COUNTER_FIRST + 1)
+#define GADGET_ID_ELEM_SCORE_UP                (GADGET_ID_COUNTER_FIRST + 2)
+#define GADGET_ID_ELEM_CONTENT_DOWN    (GADGET_ID_COUNTER_FIRST + 3)
+#define GADGET_ID_ELEM_CONTENT_TEXT    (GADGET_ID_COUNTER_FIRST + 4)
+#define GADGET_ID_ELEM_CONTENT_UP      (GADGET_ID_COUNTER_FIRST + 5)
+#define GADGET_ID_LEVEL_XSIZE_DOWN     (GADGET_ID_COUNTER_FIRST + 6)
+#define GADGET_ID_LEVEL_XSIZE_TEXT     (GADGET_ID_COUNTER_FIRST + 7)
+#define GADGET_ID_LEVEL_XSIZE_UP       (GADGET_ID_COUNTER_FIRST + 8)
+#define GADGET_ID_LEVEL_YSIZE_DOWN     (GADGET_ID_COUNTER_FIRST + 9)
+#define GADGET_ID_LEVEL_YSIZE_TEXT     (GADGET_ID_COUNTER_FIRST + 10)
+#define GADGET_ID_LEVEL_YSIZE_UP       (GADGET_ID_COUNTER_FIRST + 11)
+#define GADGET_ID_LEVEL_RANDOM_DOWN    (GADGET_ID_COUNTER_FIRST + 12)
+#define GADGET_ID_LEVEL_RANDOM_TEXT    (GADGET_ID_COUNTER_FIRST + 13)
+#define GADGET_ID_LEVEL_RANDOM_UP      (GADGET_ID_COUNTER_FIRST + 14)
+#define GADGET_ID_LEVEL_COLLECT_DOWN   (GADGET_ID_COUNTER_FIRST + 15)
+#define GADGET_ID_LEVEL_COLLECT_TEXT   (GADGET_ID_COUNTER_FIRST + 16)
+#define GADGET_ID_LEVEL_COLLECT_UP     (GADGET_ID_COUNTER_FIRST + 17)
+#define GADGET_ID_LEVEL_TIMELIMIT_DOWN (GADGET_ID_COUNTER_FIRST + 18)
+#define GADGET_ID_LEVEL_TIMELIMIT_TEXT (GADGET_ID_COUNTER_FIRST + 19)
+#define GADGET_ID_LEVEL_TIMELIMIT_UP   (GADGET_ID_COUNTER_FIRST + 20)
+#define GADGET_ID_LEVEL_TIMESCORE_DOWN (GADGET_ID_COUNTER_FIRST + 21)
+#define GADGET_ID_LEVEL_TIMESCORE_TEXT (GADGET_ID_COUNTER_FIRST + 22)
+#define GADGET_ID_LEVEL_TIMESCORE_UP   (GADGET_ID_COUNTER_FIRST + 23)
+#define GADGET_ID_SELECT_LEVEL_DOWN    (GADGET_ID_COUNTER_FIRST + 24)
+#define GADGET_ID_SELECT_LEVEL_TEXT    (GADGET_ID_COUNTER_FIRST + 25)
+#define GADGET_ID_SELECT_LEVEL_UP      (GADGET_ID_COUNTER_FIRST + 26)
 
 /* drawing area identifiers */
-#define GADGET_ID_DRAWING_LEVEL                49
-#define GADGET_ID_ELEM_CONTENT_0       50
-#define GADGET_ID_ELEM_CONTENT_1       51
-#define GADGET_ID_ELEM_CONTENT_2       52
-#define GADGET_ID_ELEM_CONTENT_3       53
-#define GADGET_ID_ELEM_CONTENT_4       54
-#define GADGET_ID_ELEM_CONTENT_5       55
-#define GADGET_ID_ELEM_CONTENT_6       56
-#define GADGET_ID_ELEM_CONTENT_7       57
-#define GADGET_ID_AMOEBA_CONTENT       58
-#define GADGET_ID_RANDOM_BACKGROUND    59
+#define GADGET_ID_DRAWING_AREA_FIRST   (GADGET_ID_COUNTER_FIRST + 27)
+
+#define GADGET_ID_DRAWING_LEVEL                (GADGET_ID_DRAWING_AREA_FIRST + 0)
+#define GADGET_ID_ELEM_CONTENT_0       (GADGET_ID_DRAWING_AREA_FIRST + 1)
+#define GADGET_ID_ELEM_CONTENT_1       (GADGET_ID_DRAWING_AREA_FIRST + 2)
+#define GADGET_ID_ELEM_CONTENT_2       (GADGET_ID_DRAWING_AREA_FIRST + 3)
+#define GADGET_ID_ELEM_CONTENT_3       (GADGET_ID_DRAWING_AREA_FIRST + 4)
+#define GADGET_ID_ELEM_CONTENT_4       (GADGET_ID_DRAWING_AREA_FIRST + 5)
+#define GADGET_ID_ELEM_CONTENT_5       (GADGET_ID_DRAWING_AREA_FIRST + 6)
+#define GADGET_ID_ELEM_CONTENT_6       (GADGET_ID_DRAWING_AREA_FIRST + 7)
+#define GADGET_ID_ELEM_CONTENT_7       (GADGET_ID_DRAWING_AREA_FIRST + 8)
+#define GADGET_ID_AMOEBA_CONTENT       (GADGET_ID_DRAWING_AREA_FIRST + 9)
+#define GADGET_ID_CUSTOM_CHANGED       (GADGET_ID_DRAWING_AREA_FIRST + 10)
+#define GADGET_ID_RANDOM_BACKGROUND    (GADGET_ID_DRAWING_AREA_FIRST + 11)
 
 /* text input identifiers */
-#define GADGET_ID_LEVEL_NAME           60
-#define GADGET_ID_LEVEL_AUTHOR         61
+#define GADGET_ID_TEXT_INPUT_FIRST     (GADGET_ID_DRAWING_AREA_FIRST + 12)
+
+#define GADGET_ID_LEVEL_NAME           (GADGET_ID_TEXT_INPUT_FIRST + 0)
+#define GADGET_ID_LEVEL_AUTHOR         (GADGET_ID_TEXT_INPUT_FIRST + 1)
+
+/* selectbox identifiers */
+#define GADGET_ID_SELECTBOX_FIRST      (GADGET_ID_TEXT_INPUT_FIRST + 2)
+
+#define GADGET_ID_CUSTOM_CHANGE_CAUSE  (GADGET_ID_SELECTBOX_FIRST + 0)
+
+/* textbutton identifiers */
+#define GADGET_ID_TEXTBUTTON_FIRST     (GADGET_ID_SELECTBOX_FIRST + 1)
+
+#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)
 
 /* gadgets for scrolling of drawing area */
-#define GADGET_ID_SCROLL_UP            62
-#define GADGET_ID_SCROLL_DOWN          63
-#define GADGET_ID_SCROLL_LEFT          64
-#define GADGET_ID_SCROLL_RIGHT         65
-#define GADGET_ID_SCROLL_HORIZONTAL    66
-#define GADGET_ID_SCROLL_VERTICAL      67
+#define GADGET_ID_SCROLLING_FIRST      (GADGET_ID_TEXTBUTTON_FIRST + 3)
+
+#define GADGET_ID_SCROLL_UP            (GADGET_ID_SCROLLING_FIRST + 0)
+#define GADGET_ID_SCROLL_DOWN          (GADGET_ID_SCROLLING_FIRST + 1)
+#define GADGET_ID_SCROLL_LEFT          (GADGET_ID_SCROLLING_FIRST + 2)
+#define GADGET_ID_SCROLL_RIGHT         (GADGET_ID_SCROLLING_FIRST + 3)
+#define GADGET_ID_SCROLL_HORIZONTAL    (GADGET_ID_SCROLLING_FIRST + 4)
+#define GADGET_ID_SCROLL_VERTICAL      (GADGET_ID_SCROLLING_FIRST + 5)
 
 /* gadgets for scrolling element list */
-#define GADGET_ID_SCROLL_LIST_UP       68
-#define GADGET_ID_SCROLL_LIST_DOWN     69
-#define GADGET_ID_SCROLL_LIST_VERTICAL 70
+#define GADGET_ID_SCROLLING_LIST_FIRST (GADGET_ID_SCROLLING_FIRST + 6)
+
+#define GADGET_ID_SCROLL_LIST_UP       (GADGET_ID_SCROLLING_LIST_FIRST + 0)
+#define GADGET_ID_SCROLL_LIST_DOWN     (GADGET_ID_SCROLLING_LIST_FIRST + 1)
+#define GADGET_ID_SCROLL_LIST_VERTICAL (GADGET_ID_SCROLLING_LIST_FIRST + 2)
 
 /* buttons for level/element properties */
-#define GADGET_ID_RANDOM_PERCENTAGE    71
-#define GADGET_ID_RANDOM_QUANTITY      72
-#define GADGET_ID_RANDOM_RESTRICTED    73
-#define GADGET_ID_DOUBLE_SPEED         74
-#define GADGET_ID_GRAVITY              75
-#define GADGET_ID_STICK_ELEMENT                76
-#define GADGET_ID_EM_SLIPPERY_GEMS     77
-#define GADGET_ID_CUSTOM_INDESTRUCTIBLE        78
-#define GADGET_ID_CUSTOM_CAN_FALL      79
-#define GADGET_ID_CUSTOM_CAN_SMASH     80
-#define GADGET_ID_CUSTOM_PUSHABLE      81
-#define GADGET_ID_CUSTOM_SLIPPERY      82
+#define GADGET_ID_CHECKBUTTON_FIRST    (GADGET_ID_SCROLLING_LIST_FIRST + 3)
+
+#define GADGET_ID_RANDOM_PERCENTAGE    (GADGET_ID_CHECKBUTTON_FIRST + 0)
+#define GADGET_ID_RANDOM_QUANTITY      (GADGET_ID_CHECKBUTTON_FIRST + 1)
+#define GADGET_ID_RANDOM_RESTRICTED    (GADGET_ID_CHECKBUTTON_FIRST + 2)
+#define GADGET_ID_DOUBLE_SPEED         (GADGET_ID_CHECKBUTTON_FIRST + 3)
+#define GADGET_ID_GRAVITY              (GADGET_ID_CHECKBUTTON_FIRST + 4)
+#define GADGET_ID_STICK_ELEMENT                (GADGET_ID_CHECKBUTTON_FIRST + 5)
+#define GADGET_ID_EM_SLIPPERY_GEMS     (GADGET_ID_CHECKBUTTON_FIRST + 6)
+#define GADGET_ID_CUSTOM_INDESTRUCTIBLE        (GADGET_ID_CHECKBUTTON_FIRST + 7)
+#define GADGET_ID_CUSTOM_CAN_FALL      (GADGET_ID_CHECKBUTTON_FIRST + 8)
+#define GADGET_ID_CUSTOM_CAN_SMASH     (GADGET_ID_CHECKBUTTON_FIRST + 9)
+#define GADGET_ID_CUSTOM_PUSHABLE      (GADGET_ID_CHECKBUTTON_FIRST + 10)
+#define GADGET_ID_CUSTOM_SLIPPERY      (GADGET_ID_CHECKBUTTON_FIRST + 11)
 
 /* gadgets for buttons in element list */
-#define GADGET_ID_ELEMENTLIST_FIRST    83
+#define GADGET_ID_ELEMENTLIST_FIRST    (GADGET_ID_CHECKBUTTON_FIRST + 12)
 #define GADGET_ID_ELEMENTLIST_LAST     (GADGET_ID_ELEMENTLIST_FIRST +  \
                                        ED_NUM_ELEMENTLIST_BUTTONS - 1)
 
 #define ED_TEXTINPUT_ID_LEVEL_FIRST    ED_TEXTINPUT_ID_LEVEL_NAME
 #define ED_TEXTINPUT_ID_LEVEL_LAST     ED_TEXTINPUT_ID_LEVEL_AUTHOR
 
+/* values for selectbox gadgets */
+#define ED_SELECTBOX_ID_CUSTOM_CHANGE_CAUSE    0
+
+#define ED_NUM_SELECTBOX                       1
+
+/* 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_NUM_TEXTBUTTON                      3
+
 /* values for checkbutton gadgets */
 #define ED_CHECKBUTTON_ID_DOUBLE_SPEED         0
 #define ED_CHECKBUTTON_ID_GRAVITY              1
 #define ED_RADIOBUTTON_ID_LEVEL_FIRST  ED_RADIOBUTTON_ID_PERCENTAGE
 #define ED_RADIOBUTTON_ID_LEVEL_LAST   ED_RADIOBUTTON_ID_QUANTITY
 
+
+/*
+  -----------------------------------------------------------------------------
+  some internally used definitions
+  -----------------------------------------------------------------------------
+*/
+
 /* values for CopyLevelToUndoBuffer() */
 #define UNDO_IMMEDIATE                 0
 #define UNDO_ACCUMULATE                        1
 
-/* values for ClearEditorGadgetInfoText() and HandleGadgetInfoText() */
-#define INFOTEXT_XPOS                  SX
-#define INFOTEXT_YPOS                  (SY + SYSIZE - MINI_TILEX + 2)
-#define INFOTEXT_XSIZE                 SXSIZE
-#define INFOTEXT_YSIZE                 MINI_TILEX
+/* values for scrollbars */
+#define ED_SCROLL_NO                   0
+#define ED_SCROLL_LEFT                 1
+#define ED_SCROLL_RIGHT                        2
+#define ED_SCROLL_UP                   4
+#define ED_SCROLL_DOWN                 8
+
+/* screens in the level editor */
+#define ED_MODE_DRAWING                        0
+#define ED_MODE_INFO                   1
+#define ED_MODE_PROPERTIES             2
+
+/* sub-screens in the element properties section */
+#define ED_MODE_PROPERTIES_INFO                ED_TEXTBUTTON_ID_PROPERTIES_INFO
+#define ED_MODE_PROPERTIES_CONFIG      ED_TEXTBUTTON_ID_PROPERTIES_CONFIG
+#define ED_MODE_PROPERTIES_ADVANCED    ED_TEXTBUTTON_ID_PROPERTIES_ADVANCED
+
+/* how many steps can be cancelled */
+#define NUM_UNDO_STEPS                 (10 + 1)
+
+/* values for elements with score */
+#define MIN_SCORE                      0
+#define MAX_SCORE                      255
+
+/* values for random placement */
+#define RANDOM_USE_PERCENTAGE          0
+#define RANDOM_USE_QUANTITY            1
+
+/* maximal size of level editor drawing area */
+#define MAX_ED_FIELDX          (2 * SCR_FIELDX)
+#define MAX_ED_FIELDY          (2 * SCR_FIELDY - 1)
+
+
+/*
+  -----------------------------------------------------------------------------
+  some internally used data structure definitions
+  -----------------------------------------------------------------------------
+*/
 
 static struct
 {
@@ -425,24 +525,12 @@ static struct
   { 'E',       "exit level editor"             }
 };
 
-/* values for random placement */
-#define RANDOM_USE_PERCENTAGE          0
-#define RANDOM_USE_QUANTITY            1
-
 static int random_placement_value = 10;
 static int random_placement_method = RANDOM_USE_QUANTITY;
 static int random_placement_background_element = EL_SAND;
 static boolean random_placement_background_restricted = FALSE;
 static boolean stick_element_properties_window = FALSE;
-
-static struct
-{
-  boolean indestructible;
-  boolean can_fall;
-  boolean can_smash;
-  boolean pushable;
-  boolean slippery;
-} custom_element_properties[NUM_CUSTOM_ELEMENTS];
+static boolean custom_element_properties[NUM_ELEMENT_PROPERTIES];
 
 static struct
 {
@@ -507,7 +595,7 @@ static struct
     0,                                 255,
     GADGET_ID_LEVEL_TIMESCORE_DOWN,    GADGET_ID_LEVEL_TIMESCORE_UP,
     GADGET_ID_LEVEL_TIMESCORE_TEXT,
-    &level.score[SC_ZEITBONUS],
+    &level.score[SC_TIME_BONUS],
     "score for each 10 seconds left",  NULL
   },
   {
@@ -553,6 +641,65 @@ static struct
   }
 };
 
+static struct ValueTextInfo options_change_cause[] =
+{
+  { 1, "specified delay"       },
+  { 2, "impact (active)"       },
+  { 3, "impact (passive)"      },
+  { 4, "touched by player"     },
+  { 5, "pressed by player"     },
+  { -1,        NULL                    }
+};
+static int index_change_cause = 0;
+
+static struct
+{
+  int x, y;
+  int gadget_id;
+  int size;
+  struct ValueTextInfo *options;
+  int *index;
+  char *text, *infotext;
+} selectbox_info[ED_NUM_SELECTBOX] =
+{
+  {
+    ED_SETTINGS_XPOS,                  ED_COUNTER_YPOS(3),
+    GADGET_ID_CUSTOM_CHANGE_CAUSE,
+    17,
+    options_change_cause, &index_change_cause,
+    "test:", "test-selectbox entry"
+  },
+};
+
+static struct
+{
+  int x, y;
+  int gadget_id;
+  int size;
+  char *value;
+  char *infotext;
+} textbutton_info[ED_NUM_TEXTBUTTON] =
+{
+  {
+    ED_SETTINGS_XPOS,                  ED_COUNTER_YPOS(1),
+    GADGET_ID_PROPERTIES_INFO,
+    11, "Information",
+    "Show information about element"
+  },
+  {
+    ED_SETTINGS_XPOS + 166,            ED_COUNTER_YPOS(1),
+    GADGET_ID_PROPERTIES_CONFIG,
+    11, "Configure",
+    "Configure element properties"
+  },
+  {
+    ED_SETTINGS_XPOS + 332,            ED_COUNTER_YPOS(1),
+    GADGET_ID_PROPERTIES_ADVANCED,
+    11, "Advanced",
+    "Advanced element configuration"
+  },
+};
+
 static struct
 {
   int xpos, ypos;
@@ -700,40 +847,43 @@ static struct
     "slip down from certain flat walls","use EM style slipping behaviour"
   },
   {
-    ED_SETTINGS_XPOS,                  ED_COUNTER_YPOS(4),
+    ED_SETTINGS_XPOS,                  ED_COUNTER_YPOS2(10),
     GADGET_ID_CUSTOM_INDESTRUCTIBLE,
-    &custom_element_properties[0].indestructible,
+    &custom_element_properties[EP_INDESTRUCTIBLE],
     "indestructible",                  "element cannot be destroyed"
   },
   {
-    ED_SETTINGS_XPOS,                  ED_COUNTER_YPOS(5),
+    ED_SETTINGS_XPOS,                  ED_COUNTER_YPOS2(11),
     GADGET_ID_CUSTOM_CAN_FALL,
-    &custom_element_properties[0].can_fall,
+    &custom_element_properties[EP_CAN_FALL],
     "can fall",                                "element can fall down"
   },
   {
-    ED_SETTINGS_XPOS,                  ED_COUNTER_YPOS(6),
+    ED_SETTINGS_XPOS,                  ED_COUNTER_YPOS2(12),
     GADGET_ID_CUSTOM_CAN_SMASH,
-    &custom_element_properties[0].can_smash,
+    &custom_element_properties[EP_CAN_SMASH],
     "can smash",                       "element can smash other elements"
   },
   {
-    ED_SETTINGS_XPOS,                  ED_COUNTER_YPOS(7),
+    ED_SETTINGS_XPOS,                  ED_COUNTER_YPOS2(13),
     GADGET_ID_CUSTOM_PUSHABLE,
-    &custom_element_properties[0].pushable,
+    &custom_element_properties[EP_PUSHABLE],
     "pushable",                                "element can be pushed"
   },
   {
-    ED_SETTINGS_XPOS,                  ED_COUNTER_YPOS(8),
+    ED_SETTINGS_XPOS,                  ED_COUNTER_YPOS2(14),
     GADGET_ID_CUSTOM_SLIPPERY,
-    &custom_element_properties[0].slippery,
+    &custom_element_properties[EP_SLIPPERY],
     "slippery",                                "other elements can fall down from it"
   }
 };
 
-/* maximal size of level editor drawing area */
-#define MAX_ED_FIELDX          (2 * SCR_FIELDX)
-#define MAX_ED_FIELDY          (2 * SCR_FIELDY - 1)
+
+/*
+  -----------------------------------------------------------------------------
+  some internally used variables
+  -----------------------------------------------------------------------------
+*/
 
 /* actual size of level editor drawing area */
 static int ed_fieldx = MAX_ED_FIELDX - 1, ed_fieldy = MAX_ED_FIELDY - 1;
@@ -763,6 +913,8 @@ static void CopyLevelToUndoBuffer(int);
 static void HandleDrawingAreas(struct GadgetInfo *);
 static void HandleCounterButtons(struct GadgetInfo *);
 static void HandleTextInputGadgets(struct GadgetInfo *);
+static void HandleSelectboxGadgets(struct GadgetInfo *);
+static void HandleTextbuttonGadgets(struct GadgetInfo *);
 static void HandleRadiobuttons(struct GadgetInfo *);
 static void HandleCheckbuttons(struct GadgetInfo *);
 static void HandleControlButtons(struct GadgetInfo *);
@@ -782,6 +934,7 @@ static int undo_buffer_position = 0;
 static int undo_buffer_steps = 0;
 
 static int edit_mode;
+static int edit_mode_properties;
 
 static int element_shift = 0;
 
@@ -1318,17 +1471,22 @@ static int editor_el_chars[] =
   EL_CHAR('X'),
   EL_CHAR('Y'),
   EL_CHAR('Z'),
-  EL_CHAR('Ä'),
+  EL_CHAR('['),
 
-  EL_CHAR('Ö'),
-  EL_CHAR('Ü'),
+  EL_CHAR('\\'),
+  EL_CHAR(']'),
   EL_CHAR('^'),
   EL_CHAR('_'),
 
-  EL_CHAR(' '),
+  EL_CHAR('©'),
+  EL_CHAR('Ä'),
+  EL_CHAR('Ö'),
+  EL_CHAR('Ü'),
+
   EL_CHAR('°'),
-  EL_CHAR('´'),
-  EL_CHAR('|')
+  EL_CHAR('®'),
+  EL_CHAR(FONT_ASCII_CURSOR),
+  EL_CHAR(' ')
 };
 static int num_editor_el_chars = SIZEOF_ARRAY_INT(editor_el_chars);
 
@@ -1551,6 +1709,13 @@ editor_elements_info[] =
     NULL                                                               }
 };
 
+
+/*
+  -----------------------------------------------------------------------------
+  functions
+  -----------------------------------------------------------------------------
+*/
+
 static void ReinitializeElementList()
 {
   int pos = 0;
@@ -1611,7 +1776,7 @@ static void ReinitializeElementListButtons()
 
 static int getCounterGadgetWidth()
 {
-  return (DXSIZE + getFontWidth(FONT_INPUT) - 2 * ED_GADGET_DISTANCE);
+  return (DXSIZE + getFontWidth(FONT_INPUT_1) - 2 * ED_GADGET_DISTANCE);
 }
 
 static int getMaxInfoTextLength()
@@ -1963,7 +2128,8 @@ static void CreateCounterButtons()
 
       if (j == 0)
       {
-       int font_type = FONT_INPUT;
+       int font_type = FONT_INPUT_1;
+       int font_type_active = FONT_INPUT_1_ACTIVE;
        int gd_width = ED_WIN_COUNT_XSIZE;
 
        id = counterbutton_info[i].gadget_id_text;
@@ -1972,6 +2138,7 @@ static void CreateCounterButtons()
        if (i == ED_COUNTER_ID_SELECT_LEVEL)
        {
          font_type = FONT_LEVEL_NUMBER;
+         font_type_active = FONT_LEVEL_NUMBER;
 
          xpos += 2 * ED_GADGET_DISTANCE;
          ypos -= ED_GADGET_DISTANCE;
@@ -1997,10 +2164,11 @@ static void CreateCounterButtons()
                          GDI_NUMBER_MAX, counterbutton_info[i].max_value,
                          GDI_TEXT_SIZE, 3,
                          GDI_TEXT_FONT, font_type,
+                         GDI_TEXT_FONT_ACTIVE, font_type_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,
-                         GDI_TEXTINPUT_DESIGN_WIDTH, gd_width,
+                         GDI_BORDER_SIZE, ED_BORDER_SIZE, ED_BORDER_SIZE,
+                         GDI_DESIGN_WIDTH, gd_width,
                          GDI_EVENT_MASK, event_mask,
                          GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
                          GDI_CALLBACK_ACTION, HandleCounterButtons,
@@ -2071,7 +2239,7 @@ static void CreateDrawingAreas()
     level_editor_gadget[id] = gi;
   }
 
-  /* ... one for the amoeba content */
+  /* ... one for the amoeba content ... */
   id = GADGET_ID_AMOEBA_CONTENT;
   gi = CreateGadget(GDI_CUSTOM_ID, id,
                    GDI_X, SX + ED_AREA_ELEM_CONTENT_XPOS,
@@ -2090,6 +2258,25 @@ static void CreateDrawingAreas()
 
   level_editor_gadget[id] = gi;
 
+  /* ... one for each custom element change target element ... */
+  id = GADGET_ID_CUSTOM_CHANGED;
+  gi = CreateGadget(GDI_CUSTOM_ID, id,
+                   GDI_X, SX + ED_AREA_ELEM_CONTENT2_XPOS,
+                   GDI_Y, SY + ED_AREA_ELEM_CONTENT2_YPOS,
+                   GDI_WIDTH, MINI_TILEX,
+                   GDI_HEIGHT, MINI_TILEY,
+                   GDI_TYPE, GD_TYPE_DRAWING_AREA,
+                   GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
+                   GDI_EVENT_MASK, event_mask,
+                   GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
+                   GDI_CALLBACK_ACTION, HandleDrawingAreas,
+                   GDI_END);
+
+  if (gi == NULL)
+    Error(ERR_EXIT, "cannot create gadget");
+
+  level_editor_gadget[id] = gi;
+
   /* ... and one for random placement background restrictions */
 
   id = GADGET_ID_RANDOM_BACKGROUND;
@@ -2141,11 +2328,12 @@ static void CreateTextInputGadgets()
                      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,
+                     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,
-                     GDI_TEXTINPUT_DESIGN_WIDTH, ED_WIN_COUNT_XSIZE,
+                     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, HandleTextInputGadgets,
@@ -2158,6 +2346,109 @@ static void CreateTextInputGadgets()
   }
 }
 
+static void CreateSelectboxGadgets()
+{
+  int max_infotext_len = getMaxInfoTextLength();
+  int i;
+
+  for (i=0; i<ED_NUM_SELECTBOX; 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 = selectbox_info[i].gadget_id;
+
+    event_mask = GD_EVENT_RELEASED |
+      GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
+
+    gd_x = DOOR_GFX_PAGEX4 + ED_SELECTBOX_XPOS;
+    gd_y = DOOR_GFX_PAGEY1 + ED_SELECTBOX_YPOS;
+
+    sprintf(infotext, "Select %s", selectbox_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 + selectbox_info[i].x,
+                     GDI_Y, SY + selectbox_info[i].y,
+                     GDI_TYPE, GD_TYPE_SELECTBOX,
+                     GDI_SELECTBOX_OPTIONS, selectbox_info[i].options,
+                     GDI_SELECTBOX_INDEX, selectbox_info[i].index,
+                     GDI_TEXT_SIZE, selectbox_info[i].size,
+                     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_BORDER_SIZE_SELECTBUTTON, getFontWidth(FONT_INPUT_1),
+                     GDI_DESIGN_WIDTH, ED_WIN_COUNT_XSIZE,
+                     GDI_EVENT_MASK, event_mask,
+                     GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
+                     GDI_CALLBACK_ACTION, HandleSelectboxGadgets,
+                     GDI_END);
+
+    if (gi == NULL)
+      Error(ERR_EXIT, "cannot create gadget");
+
+    level_editor_gadget[id] = gi;
+  }
+}
+
+static void CreateTextbuttonGadgets()
+{
+  int max_infotext_len = getMaxInfoTextLength();
+  int 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;
+    struct GadgetInfo *gi;
+    unsigned long event_mask;
+    char infotext[MAX_OUTPUT_LINESIZE + 1];
+    int id = textbutton_info[i].gadget_id;
+
+    event_mask = GD_EVENT_RELEASED;
+
+    gd_x1 = DOOR_GFX_PAGEX4 + ED_TEXTBUTTON_XPOS;
+    gd_x2 = DOOR_GFX_PAGEX3 + ED_TEXTBUTTON_XPOS;
+    gd_y1 = DOOR_GFX_PAGEY1 + ED_TEXTBUTTON_YPOS;
+    gd_y2 = DOOR_GFX_PAGEY1 + ED_TEXTBUTTON_INACTIVE_YPOS;
+
+    sprintf(infotext, "%s", textbutton_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 + textbutton_info[i].x,
+                     GDI_Y, SY + textbutton_info[i].y,
+                     GDI_TYPE, GD_TYPE_TEXT_BUTTON,
+                     GDI_TEXT_VALUE, textbutton_info[i].value,
+                     GDI_TEXT_SIZE, textbutton_info[i].size,
+                     GDI_TEXT_FONT, FONT_INPUT_2_ACTIVE,
+                     GDI_TEXT_FONT_ACTIVE, FONT_INPUT_2,
+                     GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y1,
+                     GDI_ALT_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y2,
+                     GDI_BORDER_SIZE, ED_BORDER2_SIZE, ED_BORDER_SIZE,
+                     GDI_DESIGN_WIDTH, ED_WIN_COUNT_XSIZE,
+                     GDI_DECORATION_SHIFTING, 1, 1,
+                     GDI_EVENT_MASK, event_mask,
+                     GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
+                     GDI_CALLBACK_ACTION, HandleTextbuttonGadgets,
+                     GDI_END);
+
+    if (gi == NULL)
+      Error(ERR_EXIT, "cannot create gadget");
+
+    level_editor_gadget[id] = gi;
+  }
+}
+
 static void CreateScrollbarGadgets()
 {
   int i;
@@ -2215,7 +2506,7 @@ static void CreateScrollbarGadgets()
                      GDI_STATE, GD_BUTTON_UNPRESSED,
                      GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
                      GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
-                     GDI_BORDER_SIZE, ED_BORDER_SIZE,
+                     GDI_BORDER_SIZE, ED_BORDER_SIZE, ED_BORDER_SIZE,
                      GDI_EVENT_MASK, event_mask,
                      GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
                      GDI_CALLBACK_ACTION, HandleControlButtons,
@@ -2313,14 +2604,23 @@ static void CreateCheckbuttonGadgets()
 
 void CreateLevelEditorGadgets()
 {
+  int old_game_status = game_status;
+
+  /* setting 'game_status' is needed to get the right fonts for the editor */
+  game_status = LEVELED;
+
   ReinitializeElementList();
 
   CreateControlButtons();
   CreateCounterButtons();
   CreateDrawingAreas();
   CreateTextInputGadgets();
+  CreateSelectboxGadgets();
+  CreateTextbuttonGadgets();
   CreateScrollbarGadgets();
   CreateCheckbuttonGadgets();
+
+  game_status = old_game_status;
 }
 
 void FreeLevelEditorGadgets()
@@ -2373,6 +2673,16 @@ static void MapTextInputGadget(int id)
   MapGadget(level_editor_gadget[textinput_info[id].gadget_id]);
 }
 
+static void MapSelectboxGadget(int id)
+{
+  MapGadget(level_editor_gadget[selectbox_info[id].gadget_id]);
+}
+
+static void MapTextbuttonGadget(int id)
+{
+  MapGadget(level_editor_gadget[textbutton_info[id].gadget_id]);
+}
+
 static void MapRadiobuttonGadget(int id)
 {
   MapGadget(level_editor_gadget[radiobutton_info[id].gadget_id]);
@@ -2490,67 +2800,20 @@ static void CopyPlayfield(short src[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
       dst[x][y] = src[x][y];
 }
 
-static void CopyCustomElementPropertiesToEditor()
+static void CopyCustomElementPropertiesToEditor(int element)
 {
   int i;
 
-  for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
-  {
-    int element = EL_CUSTOM_START + i;
-    int properties = Properties1[element];
-
-    custom_element_properties[i].indestructible =
-      ((properties & EP_BIT_INDESTRUCTIBLE) != 0 ? TRUE : FALSE);
-
-    custom_element_properties[i].can_fall =
-      ((properties & EP_BIT_CAN_FALL) != 0 ? TRUE : FALSE);
-
-    custom_element_properties[i].can_smash =
-      ((properties & EP_BIT_CAN_SMASH) != 0 ? TRUE : FALSE);
-
-    custom_element_properties[i].pushable =
-      ((properties & EP_BIT_PUSHABLE) != 0 ? TRUE : FALSE);
-
-    custom_element_properties[i].slippery =
-      ((properties & EP_BIT_SLIPPERY) != 0 ? TRUE : FALSE);
-  }
+  for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
+    custom_element_properties[i] = HAS_PROPERTY(element, i);
 }
 
-static void CopyCustomElementPropertiesToGame()
+static void CopyCustomElementPropertiesToGame(int element)
 {
   int i;
 
-  for (i=0; i < NUM_CUSTOM_ELEMENTS; i++)
-  {
-    int element = EL_CUSTOM_START + i;
-
-    Properties1[element] = EP_BITMASK_DEFAULT;
-
-    if (custom_element_properties[i].indestructible)
-      Properties1[element] |= EP_BIT_INDESTRUCTIBLE;
-    else
-      Properties1[element] &= ~EP_BIT_INDESTRUCTIBLE;
-
-    if (custom_element_properties[i].can_fall)
-      Properties1[element] |= EP_BIT_CAN_FALL;
-    else
-      Properties1[element] &= ~EP_BIT_CAN_FALL;
-
-    if (custom_element_properties[i].can_smash)
-      Properties1[element] |= EP_BIT_CAN_SMASH;
-    else
-      Properties1[element] &= ~EP_BIT_CAN_SMASH;
-
-    if (custom_element_properties[i].pushable)
-      Properties1[element] |= EP_BIT_PUSHABLE;
-    else
-      Properties1[element] &= ~EP_BIT_PUSHABLE;
-
-    if (custom_element_properties[i].slippery)
-      Properties1[element] |= EP_BIT_SLIPPERY;
-    else
-      Properties1[element] &= ~EP_BIT_SLIPPERY;
-  }
+  for (i=0; i < NUM_ELEMENT_PROPERTIES; i++)
+    SET_PROPERTY(element, i, custom_element_properties[i]);
 }
 
 void DrawLevelEd()
@@ -2568,8 +2831,10 @@ void DrawLevelEd()
   else
   {
     edit_mode = ED_MODE_DRAWING;
+    edit_mode_properties = ED_MODE_PROPERTIES_INFO;
 
     ResetUndoBuffer();
+
     level_xpos = -1;
     level_ypos = -1;
   }
@@ -2934,6 +3199,32 @@ static void DrawAmoebaContentArea()
   MapDrawingArea(GADGET_ID_AMOEBA_CONTENT);
 }
 
+static void DrawCustomChangedArea()
+{
+  int area_x = ED_AREA_ELEM_CONTENT2_XPOS / MINI_TILEX;
+  int area_y = ED_AREA_ELEM_CONTENT2_YPOS / MINI_TILEY;
+  int area_sx = SX + ED_AREA_ELEM_CONTENT2_XPOS;
+  int area_sy = SY + ED_AREA_ELEM_CONTENT2_YPOS;
+  int i = properties_element - EL_CUSTOM_START;
+
+  if (!IS_CUSTOM_ELEMENT(properties_element))
+  {
+    /* this should never happen */
+    Error(ERR_WARN, "element %d is no custom element", properties_element);
+
+    return;
+  }
+
+  ElementContent[0][0][0] = level.custom_element_successor[i];
+
+  DrawElementBorder(area_sx, area_sy, MINI_TILEX, MINI_TILEY);
+  DrawMiniElement(area_x, area_y, ElementContent[0][0][0]);
+
+  DrawText(area_sx + TILEX, area_sy + 1, "Element after change", FONT_TEXT_1);
+
+  MapDrawingArea(GADGET_ID_CUSTOM_CHANGED);
+}
+
 static void DrawElementContentAreas()
 {
   int counter_id = ED_COUNTER_ID_ELEM_CONTENT;
@@ -2998,104 +3289,85 @@ static void DrawElementContentAreas()
 #define TEXT_SPEED             "Speed of amoeba growth"
 #define TEXT_DURATION          "Duration when activated"
 
-static void DrawPropertiesWindow()
+static struct
+{
+  int element;
+  int *value;
+  char *text;
+} elements_with_counter[] =
+{
+  { EL_EMERALD,                &level.score[SC_EMERALD],       TEXT_COLLECTING },
+  { EL_BD_DIAMOND,     &level.score[SC_EMERALD],       TEXT_COLLECTING },
+  { EL_EMERALD_YELLOW, &level.score[SC_EMERALD],       TEXT_COLLECTING },
+  { EL_EMERALD_RED,    &level.score[SC_EMERALD],       TEXT_COLLECTING },
+  { EL_EMERALD_PURPLE, &level.score[SC_EMERALD],       TEXT_COLLECTING },
+  { EL_DIAMOND,                &level.score[SC_DIAMOND],       TEXT_COLLECTING },
+  { EL_BUG_RIGHT,      &level.score[SC_BUG],           TEXT_SMASHING   },
+  { EL_BUG_UP,         &level.score[SC_BUG],           TEXT_SMASHING   },
+  { EL_BUG_LEFT,       &level.score[SC_BUG],           TEXT_SMASHING   },
+  { EL_BUG_DOWN,       &level.score[SC_BUG],           TEXT_SMASHING   },
+  { EL_BD_BUTTERFLY_RIGHT,&level.score[SC_BUG],                TEXT_SMASHING   },
+  { EL_BD_BUTTERFLY_UP,   &level.score[SC_BUG],                TEXT_SMASHING   },
+  { EL_BD_BUTTERFLY_LEFT, &level.score[SC_BUG],                TEXT_SMASHING   },
+  { EL_BD_BUTTERFLY_DOWN, &level.score[SC_BUG],                TEXT_SMASHING   },
+  { EL_SPACESHIP_RIGHT,        &level.score[SC_SPACESHIP],     TEXT_SMASHING   },
+  { EL_SPACESHIP_UP,   &level.score[SC_SPACESHIP],     TEXT_SMASHING   },
+  { EL_SPACESHIP_LEFT, &level.score[SC_SPACESHIP],     TEXT_SMASHING   },
+  { EL_SPACESHIP_DOWN, &level.score[SC_SPACESHIP],     TEXT_SMASHING   },
+  { EL_BD_FIREFLY_RIGHT,&level.score[SC_SPACESHIP],    TEXT_SMASHING   },
+  { EL_BD_FIREFLY_UP,  &level.score[SC_SPACESHIP],     TEXT_SMASHING   },
+  { EL_BD_FIREFLY_LEFT, &level.score[SC_SPACESHIP],    TEXT_SMASHING   },
+  { EL_BD_FIREFLY_DOWN, &level.score[SC_SPACESHIP],    TEXT_SMASHING   },
+  { EL_YAMYAM,         &level.score[SC_YAMYAM],        TEXT_SMASHING   },
+  { EL_DARK_YAMYAM,    &level.score[SC_YAMYAM],        TEXT_SMASHING   },
+  { EL_ROBOT,          &level.score[SC_ROBOT],         TEXT_SMASHING   },
+  { EL_PACMAN_RIGHT,   &level.score[SC_PACMAN],        TEXT_SMASHING   },
+  { EL_PACMAN_UP,      &level.score[SC_PACMAN],        TEXT_SMASHING   },
+  { EL_PACMAN_LEFT,    &level.score[SC_PACMAN],        TEXT_SMASHING   },
+  { EL_PACMAN_DOWN,    &level.score[SC_PACMAN],        TEXT_SMASHING   },
+  { EL_NUT,            &level.score[SC_NUT],           TEXT_CRACKING   },
+  { EL_DYNAMITE,       &level.score[SC_DYNAMITE],      TEXT_COLLECTING },
+  { EL_KEY_1,          &level.score[SC_KEY],           TEXT_COLLECTING },
+  { EL_KEY_2,          &level.score[SC_KEY],           TEXT_COLLECTING },
+  { EL_KEY_3,          &level.score[SC_KEY],           TEXT_COLLECTING },
+  { EL_KEY_4,          &level.score[SC_KEY],           TEXT_COLLECTING },
+  { EL_EM_KEY_1_FILE,  &level.score[SC_KEY],           TEXT_COLLECTING },
+  { EL_EM_KEY_2_FILE,  &level.score[SC_KEY],           TEXT_COLLECTING },
+  { EL_EM_KEY_3_FILE,  &level.score[SC_KEY],           TEXT_COLLECTING },
+  { EL_EM_KEY_4_FILE,  &level.score[SC_KEY],           TEXT_COLLECTING },
+  { EL_AMOEBA_WET,     &level.amoeba_speed,            TEXT_SPEED      },
+  { EL_AMOEBA_DRY,     &level.amoeba_speed,            TEXT_SPEED      },
+  { EL_AMOEBA_FULL,    &level.amoeba_speed,            TEXT_SPEED      },
+  { EL_BD_AMOEBA,      &level.amoeba_speed,            TEXT_SPEED      },
+  { EL_MAGIC_WALL,     &level.time_magic_wall,         TEXT_DURATION   },
+  { EL_ROBOT_WHEEL,    &level.time_wheel,              TEXT_DURATION   },
+  { -1,                        NULL,                           NULL            }
+};
+
+static boolean checkPropertiesConfig()
+{
+  int i;
+
+  if (IS_GEM(properties_element) ||
+      IS_CUSTOM_ELEMENT(properties_element) ||
+      HAS_CONTENT(properties_element))
+    return TRUE;
+  else
+    for (i=0; elements_with_counter[i].element != -1; i++)
+      if (elements_with_counter[i].element == properties_element)
+       return TRUE;
+
+  return FALSE;
+}
+
+static void DrawPropertiesConfig()
 {
   int counter_id = ED_COUNTER_ID_ELEM_SCORE;
-  int num_elements_in_level;
-  float percentage;
   int xoffset_right = getCounterGadgetWidth();
   int yoffset_right = ED_BORDER_SIZE;
   int xoffset_right2 = ED_CHECKBUTTON_XSIZE + 2 * ED_GADGET_DISTANCE;
   int yoffset_right2 = ED_BORDER_SIZE;
-  int xstart = 2;
-  int ystart = 4;
   int i, x, y;
-  static struct
-  {
-    int element;
-    int *value;
-    char *text;
-  } elements_with_counter[] =
-  {
-    { EL_EMERALD,      &level.score[SC_EDELSTEIN],     TEXT_COLLECTING },
-    { EL_BD_DIAMOND,   &level.score[SC_EDELSTEIN],     TEXT_COLLECTING },
-    { EL_EMERALD_YELLOW,&level.score[SC_EDELSTEIN],    TEXT_COLLECTING },
-    { EL_EMERALD_RED,  &level.score[SC_EDELSTEIN],     TEXT_COLLECTING },
-    { EL_EMERALD_PURPLE,&level.score[SC_EDELSTEIN],    TEXT_COLLECTING },
-    { EL_DIAMOND,      &level.score[SC_DIAMANT],       TEXT_COLLECTING },
-    { EL_BUG_RIGHT,    &level.score[SC_KAEFER],        TEXT_SMASHING },
-    { EL_BUG_UP,       &level.score[SC_KAEFER],        TEXT_SMASHING },
-    { EL_BUG_LEFT,     &level.score[SC_KAEFER],        TEXT_SMASHING },
-    { EL_BUG_DOWN,     &level.score[SC_KAEFER],        TEXT_SMASHING },
-    { EL_BD_BUTTERFLY_RIGHT,&level.score[SC_KAEFER],   TEXT_SMASHING },
-    { EL_BD_BUTTERFLY_UP,   &level.score[SC_KAEFER],   TEXT_SMASHING },
-    { EL_BD_BUTTERFLY_LEFT, &level.score[SC_KAEFER],   TEXT_SMASHING },
-    { EL_BD_BUTTERFLY_DOWN, &level.score[SC_KAEFER],   TEXT_SMASHING },
-    { EL_SPACESHIP_RIGHT,&level.score[SC_FLIEGER],     TEXT_SMASHING },
-    { EL_SPACESHIP_UP,  &level.score[SC_FLIEGER],      TEXT_SMASHING },
-    { EL_SPACESHIP_LEFT, &level.score[SC_FLIEGER],     TEXT_SMASHING },
-    { EL_SPACESHIP_DOWN, &level.score[SC_FLIEGER],     TEXT_SMASHING },
-    { EL_BD_FIREFLY_RIGHT,&level.score[SC_FLIEGER],    TEXT_SMASHING },
-    { EL_BD_FIREFLY_UP,          &level.score[SC_FLIEGER],     TEXT_SMASHING },
-    { EL_BD_FIREFLY_LEFT, &level.score[SC_FLIEGER],    TEXT_SMASHING },
-    { EL_BD_FIREFLY_DOWN, &level.score[SC_FLIEGER],    TEXT_SMASHING },
-    { EL_YAMYAM,       &level.score[SC_MAMPFER],       TEXT_SMASHING },
-    { EL_DARK_YAMYAM,  &level.score[SC_MAMPFER],       TEXT_SMASHING },
-    { EL_ROBOT,                &level.score[SC_ROBOT],         TEXT_SMASHING },
-    { EL_PACMAN_RIGHT, &level.score[SC_PACMAN],        TEXT_SMASHING },
-    { EL_PACMAN_UP,    &level.score[SC_PACMAN],        TEXT_SMASHING },
-    { EL_PACMAN_LEFT,  &level.score[SC_PACMAN],        TEXT_SMASHING },
-    { EL_PACMAN_DOWN,  &level.score[SC_PACMAN],        TEXT_SMASHING },
-    { EL_NUT,          &level.score[SC_KOKOSNUSS],     TEXT_CRACKING },
-    { EL_DYNAMITE,     &level.score[SC_DYNAMIT],       TEXT_COLLECTING },
-    { EL_KEY_1,                &level.score[SC_SCHLUESSEL],    TEXT_COLLECTING },
-    { EL_KEY_2,                &level.score[SC_SCHLUESSEL],    TEXT_COLLECTING },
-    { EL_KEY_3,                &level.score[SC_SCHLUESSEL],    TEXT_COLLECTING },
-    { EL_KEY_4,                &level.score[SC_SCHLUESSEL],    TEXT_COLLECTING },
-    { EL_EM_KEY_1_FILE,        &level.score[SC_SCHLUESSEL],    TEXT_COLLECTING },
-    { EL_EM_KEY_2_FILE,        &level.score[SC_SCHLUESSEL],    TEXT_COLLECTING },
-    { EL_EM_KEY_3_FILE,        &level.score[SC_SCHLUESSEL],    TEXT_COLLECTING },
-    { EL_EM_KEY_4_FILE,        &level.score[SC_SCHLUESSEL],    TEXT_COLLECTING },
-    { EL_AMOEBA_WET,   &level.amoeba_speed,            TEXT_SPEED },
-    { EL_AMOEBA_DRY,   &level.amoeba_speed,            TEXT_SPEED },
-    { EL_AMOEBA_FULL,  &level.amoeba_speed,            TEXT_SPEED },
-    { EL_BD_AMOEBA,    &level.amoeba_speed,            TEXT_SPEED },
-    { EL_MAGIC_WALL,   &level.time_magic_wall,         TEXT_DURATION },
-    { EL_ROBOT_WHEEL,  &level.time_wheel,              TEXT_DURATION },
-    { -1, NULL, NULL }
-  };
-
-  SetMainBackgroundImage(IMG_BACKGROUND_EDITOR);
-  ClearWindow();
-  UnmapLevelEditorWindowGadgets();
-
-  DrawText(SX + ED_SETTINGS2_XPOS, SY + ED_SETTINGS_YPOS,
-          "Element Settings", FONT_TITLE_1);
-
-  DrawElementBorder(SX + xstart * MINI_TILEX,
-                   SY + ystart * MINI_TILEY + MINI_TILEY / 2,
-                   TILEX, TILEY);
-  DrawGraphicAnimationExt(drawto,
-                         SX + xstart * MINI_TILEX,
-                         SY + ystart * MINI_TILEY + MINI_TILEY / 2,
-                         el2edimg(properties_element), -1, NO_MASKING);
-
-  FrameCounter = 0;    /* restart animation frame counter */
-
-  DrawTextF((xstart + 3) * MINI_TILEX, (ystart + 1) * MINI_TILEY,
-           FONT_TEXT_1, getElementInfoText(properties_element));
-
-  num_elements_in_level = 0;
-  for (y=0; y<lev_fieldy; y++) 
-    for (x=0; x<lev_fieldx; x++)
-      if (Feld[x][y] == properties_element)
-       num_elements_in_level++;
-  percentage = num_elements_in_level * 100.0 / (lev_fieldx * lev_fieldy);
-
-  DrawTextF(ED_SETTINGS_XPOS, 5 * TILEY, FONT_TEXT_1, "In this level:");
-  DrawTextF(ED_SETTINGS_XPOS + 15 * getFontWidth(FONT_TEXT_1), 5 * TILEY,
-           FONT_TEXT_2, "%d (%.2f%%)", num_elements_in_level,
-           percentage);
 
   /* check if there are elements where a score can be chosen for */
   for (i=0; elements_with_counter[i].element != -1; i++)
@@ -3114,7 +3386,8 @@ static void DrawPropertiesWindow()
     }
   }
 
-  if (HAS_CONTENT(properties_element))
+  if (HAS_CONTENT(properties_element) ||
+      IS_CUSTOM_ELEMENT(properties_element))
   {
     /* draw stickybutton gadget */
     i = ED_CHECKBUTTON_ID_STICK_ELEMENT;
@@ -3126,10 +3399,15 @@ static void DrawPropertiesWindow()
                 GDI_CHECKED, *checkbutton_info[i].value, GDI_END);
     MapCheckbuttonGadget(i);
 
-    if (IS_AMOEBOID(properties_element))
-      DrawAmoebaContentArea();
-    else
-      DrawElementContentAreas();
+    if (HAS_CONTENT(properties_element))
+    {
+      if (IS_AMOEBOID(properties_element))
+       DrawAmoebaContentArea();
+      else
+       DrawElementContentAreas();
+    }
+    else if (IS_CUSTOM_ELEMENT(properties_element))
+      DrawCustomChangedArea();
   }
 
   if (IS_GEM(properties_element))
@@ -3147,70 +3425,400 @@ static void DrawPropertiesWindow()
 
   if (IS_CUSTOM_ELEMENT(properties_element))
   {
-    int nr = properties_element - EL_CUSTOM_START;
+    CopyCustomElementPropertiesToEditor(properties_element);
 
-    CopyCustomElementPropertiesToEditor();
+    for (i =  ED_CHECKBUTTON_ID_CUSTOM_INDESTRUCTIBLE;
+        i <= ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY; i++)
+    {
+      /* draw checkbutton gadget */
+      x = checkbutton_info[i].x + xoffset_right2;
+      y = checkbutton_info[i].y + yoffset_right2;
+
+      DrawTextF(x, y, FONT_TEXT_1, checkbutton_info[i].text);
+      ModifyGadget(level_editor_gadget[checkbutton_info[i].gadget_id],
+                  GDI_CHECKED, *checkbutton_info[i].value, GDI_END);
+      MapCheckbuttonGadget(i);
+    }
 
-    /* draw checkbutton gadget */
-    i = ED_CHECKBUTTON_ID_CUSTOM_INDESTRUCTIBLE;
-    x = checkbutton_info[i].x + xoffset_right2;
-    y = checkbutton_info[i].y + yoffset_right2;
+    /* draw selectbox gadget */
+    i = ED_SELECTBOX_ID_CUSTOM_CHANGE_CAUSE;
+    x = selectbox_info[i].x + xoffset_right2;
+    y = selectbox_info[i].y + yoffset_right2;
 
-    checkbutton_info[i].value = &custom_element_properties[nr].indestructible;
+    selectbox_info[i].index = &index_change_cause;
 
-    DrawTextF(x, y, FONT_TEXT_1, checkbutton_info[i].text);
-    ModifyGadget(level_editor_gadget[checkbutton_info[i].gadget_id],
-                GDI_CHECKED, *checkbutton_info[i].value, GDI_END);
-    MapCheckbuttonGadget(i);
+    DrawTextF(x, y, FONT_TEXT_1, selectbox_info[i].text);
+    ModifyGadget(level_editor_gadget[selectbox_info[i].gadget_id],
+                GDI_SELECTBOX_INDEX, *selectbox_info[i].index, GDI_END);
+    MapSelectboxGadget(i);
+  }
+}
 
-    /* draw checkbutton gadget */
-    i = ED_CHECKBUTTON_ID_CUSTOM_CAN_FALL;
-    x = checkbutton_info[i].x + xoffset_right2;
-    y = checkbutton_info[i].y + yoffset_right2;
+char *getElementDescriptionFilename(int element)
+{
+  char *docs_dir = options.docs_directory;
+  char *elements_subdir = "elements";
+  static char *filename = NULL;
+  char basename[MAX_FILENAME_LEN];
 
-    checkbutton_info[i].value = &custom_element_properties[nr].can_fall;
+  if (filename != NULL)
+    free(filename);
 
-    DrawTextF(x, y, FONT_TEXT_1, checkbutton_info[i].text);
-    ModifyGadget(level_editor_gadget[checkbutton_info[i].gadget_id],
-                GDI_CHECKED, *checkbutton_info[i].value, GDI_END);
-    MapCheckbuttonGadget(i);
+  /* 1st try: look for element description file for exactly this element */
+  sprintf(basename, "%s.txt", element_info[element].token_name);
+  filename = getPath3(docs_dir, elements_subdir, basename);
+  if (fileExists(filename))
+    return filename;
 
-    /* draw checkbutton gadget */
-    i = ED_CHECKBUTTON_ID_CUSTOM_CAN_SMASH;
-    x = checkbutton_info[i].x + xoffset_right2;
-    y = checkbutton_info[i].y + yoffset_right2;
+  free(filename);
 
-    checkbutton_info[i].value = &custom_element_properties[nr].can_smash;
+  /* 2nd try: look for element description file for this element's class */
+  sprintf(basename, "%s.txt", element_info[element].class_name);
+  filename = getPath3(docs_dir, elements_subdir, basename);
+  if (fileExists(filename))
+    return filename;
 
-    DrawTextF(x, y, FONT_TEXT_1, checkbutton_info[i].text);
-    ModifyGadget(level_editor_gadget[checkbutton_info[i].gadget_id],
-                GDI_CHECKED, *checkbutton_info[i].value, GDI_END);
-    MapCheckbuttonGadget(i);
+  return NULL;
+}
 
-    /* draw checkbutton gadget */
-    i = ED_CHECKBUTTON_ID_CUSTOM_PUSHABLE;
-    x = checkbutton_info[i].x + xoffset_right2;
-    y = checkbutton_info[i].y + yoffset_right2;
+static boolean PrintInfoText(char *text, int font_nr, int screen_line)
+{
+  int font_height = getFontHeight(font_nr);
+  int pad_x = ED_SETTINGS_XPOS;
+  int pad_y = 5 * TILEY;
+  int sx = SX + pad_x;
+  int sy = SY + pad_y;
+  int max_lines_per_screen = (SYSIZE - pad_y) / font_height - 1;
 
-    checkbutton_info[i].value = &custom_element_properties[nr].pushable;
+  if (screen_line >= max_lines_per_screen)
+    return FALSE;
 
-    DrawTextF(x, y, FONT_TEXT_1, checkbutton_info[i].text);
-    ModifyGadget(level_editor_gadget[checkbutton_info[i].gadget_id],
-                GDI_CHECKED, *checkbutton_info[i].value, GDI_END);
-    MapCheckbuttonGadget(i);
+  DrawText(sx, sy + screen_line * font_height, text, font_nr);
 
-    /* draw checkbutton gadget */
-    i = ED_CHECKBUTTON_ID_CUSTOM_SLIPPERY;
-    x = checkbutton_info[i].x + xoffset_right2;
-    y = checkbutton_info[i].y + yoffset_right2;
+  return TRUE;
+}
+
+static int PrintElementDescriptionFromFile(char *filename, int screen_line)
+{
+  int font_nr = FONT_TEXT_2;
+  int font_width = getFontWidth(font_nr);
+  int pad_x = ED_SETTINGS_XPOS;
+  int max_chars_per_line = (SXSIZE - 2 * pad_x) / font_width;
+  char line[MAX_LINE_LEN];
+  char buffer[max_chars_per_line + 1];
+  int buffer_len;
+  int lines_printed = 0;
+  FILE *file;
+
+  if (filename == NULL)
+    return 0;
+
+  if (!(file = fopen(filename, MODE_READ)))
+    return 0;
+
+  buffer[0] = '\0';
+  buffer_len = 0;
+
+  while(!feof(file))
+  {
+    char *line_ptr, *word_ptr;
+    boolean last_line_was_empty = TRUE;
 
-    checkbutton_info[i].value = &custom_element_properties[nr].slippery;
+    /* read next line of input file */
+    if (!fgets(line, MAX_LINE_LEN, file))
+      break;
 
-    DrawTextF(x, y, FONT_TEXT_1, checkbutton_info[i].text);
-    ModifyGadget(level_editor_gadget[checkbutton_info[i].gadget_id],
-                GDI_CHECKED, *checkbutton_info[i].value, GDI_END);
-    MapCheckbuttonGadget(i);
+    /* skip comments (lines directly beginning with '#') */
+    if (line[0] == '#')
+      continue;
+
+    /* cut trailing newline from input line */
+    for (line_ptr = line; *line_ptr; line_ptr++)
+    {
+      if (*line_ptr == '\n' || *line_ptr == '\r')
+      {
+       *line_ptr = '\0';
+       break;
+      }
+    }
+
+    if (strlen(line) == 0)             /* special case: force empty line */
+      strcpy(line, "\n");
+
+    word_ptr = line;
+
+    while (*word_ptr)
+    {
+      boolean print_buffer = FALSE;
+      int word_len;
+
+      /* skip leading whitespaces */
+      while (*word_ptr == ' ' || *word_ptr == '\t')
+       word_ptr++;
+
+      line_ptr = word_ptr;
+      word_len = 0;
+
+      /* look for end of next word */
+      while (*line_ptr != ' ' && *line_ptr != '\t' && *line_ptr != '\0')
+      {
+       line_ptr++;
+       word_len++;
+      }
+
+      if (word_len == 0)
+      {
+       continue;
+      }
+      else if (*word_ptr == '\n')      /* special case: force empty line */
+      {
+       if (buffer_len == 0)
+         word_ptr++;
+
+       /* prevent printing of multiple empty lines */
+       if (buffer_len > 0 || !last_line_was_empty)
+         print_buffer = TRUE;
+      }
+      else if (word_len < max_chars_per_line - buffer_len)
+      {
+       /* word fits into text buffer -- add word */
+
+       if (buffer_len > 0)
+         buffer[buffer_len++] = ' ';
+
+       strncpy(&buffer[buffer_len], word_ptr, word_len);
+       buffer_len += word_len;
+       buffer[buffer_len] = '\0';
+       word_ptr += word_len;
+      }
+      else if (buffer_len > 0)
+      {
+       /* not enough space left for word in text buffer -- print buffer */
+
+       print_buffer = TRUE;
+      }
+      else
+      {
+       /* word does not fit at all into empty text buffer -- cut word */
+
+       strncpy(buffer, word_ptr, max_chars_per_line);
+       buffer[max_chars_per_line] = '\0';
+       word_ptr += max_chars_per_line;
+       print_buffer = TRUE;
+      }
+
+      if (print_buffer)
+      {
+       if (!PrintInfoText(buffer, font_nr, screen_line + lines_printed))
+         return lines_printed;
+
+       last_line_was_empty = (buffer_len == 0);
+       lines_printed++;
+
+       buffer[0] = '\0';
+       buffer_len = 0;
+       print_buffer = FALSE;
+      }
+    }
+  }
+
+  fclose(file);
+
+  if (buffer_len > 0)
+    if (PrintInfoText(buffer, font_nr, screen_line + lines_printed))
+      lines_printed++;
+
+  return lines_printed;
+}
+
+static void DrawPropertiesTabulatorGadgets()
+{
+  struct GadgetInfo *gd_gi = level_editor_gadget[GADGET_ID_PROPERTIES_INFO];
+  struct GadgetDesign *gd = &gd_gi->alt_design[GD_BUTTON_UNPRESSED];
+  int gd_x = gd->x + gd_gi->border.width / 2;
+  int gd_y = gd->y + gd_gi->height - 1;
+  Pixel line_color = GetPixel(gd->bitmap, gd_x, gd_y);
+  int id_first = ED_TEXTBUTTON_ID_PROPERTIES_INFO;
+  int id_last  = ED_TEXTBUTTON_ID_PROPERTIES_INFO;
+  int i;
+
+  /* draw additional "configure" tabulator for configurable elements */
+  if (checkPropertiesConfig())
+    id_last = ED_TEXTBUTTON_ID_PROPERTIES_CONFIG;
+
+  /* draw additional "advanced" tabulator for custom elements */
+  if (IS_CUSTOM_ELEMENT(properties_element))
+    id_last = ED_TEXTBUTTON_ID_PROPERTIES_ADVANCED;
+
+  for (i=id_first; i <= id_last; i++)
+  {
+    int gadget_id = textbutton_info[i].gadget_id;
+    struct GadgetInfo *gi = level_editor_gadget[gadget_id];
+    boolean active = (i != edit_mode_properties);
+    Pixel color = (active ? BLACK_PIXEL : line_color);
+
+    /* draw solid or black line below tabulator button */
+    FillRectangle(drawto, gi->x, gi->y + gi->height, gi->width, 1, color);
+
+    ModifyGadget(gi, GDI_ACTIVE, active, GDI_END);
+    MapTextbuttonGadget(i);
+  }
+
+  /* draw little border line below tabulator buttons */
+  FillRectangle(drawto, gd_gi->x, gd_gi->y + gd_gi->height + 1,
+               3 * gd_gi->width + 2 * ED_GADGET_DISTANCE, ED_GADGET_DISTANCE,
+               line_color);
+}
+
+static void DrawPropertiesInfo()
+{
+  static struct
+  {
+    int value;
+    char *text;
+  }
+  properties[] =
+  {
+    { EP_AMOEBALIVE,           "- living amoeba"               },
+    { EP_AMOEBOID,             "- amoeboid"                    },
+    { EP_PFORTE,               "- pforte"                      },
+    { EP_SOLID,                        "- solid"                       },
+    { EP_INDESTRUCTIBLE,       "- undestructible"              },
+    { EP_SLIPPERY,             "- slippery"                    },
+    { EP_ENEMY,                        "- enemy"                       },
+    { EP_MAUER,                        "- mauer"                       },
+    { EP_CAN_FALL,             "- can fall"                    },
+    { EP_CAN_SMASH,            "- can smash"                   },
+    { EP_CAN_CHANGE,           "- can change"                  },
+    { EP_CAN_MOVE,             "- can move"                    },
+    { EP_COULD_MOVE,           "- could move"                  },
+    { EP_DONT_TOUCH,           "- don't touch"                 },
+    { EP_DONT_GO_TO,           "- don't go to"                 },
+    { EP_FOOD_DARK_YAMYAM,     "- food for dark yamyam"        },
+    { EP_BD_ELEMENT,           "- BD style"                    },
+    { EP_SB_ELEMENT,           "- SB style"                    },
+    { EP_GEM,                  "- gem"                         },
+    { EP_INACTIVE,             "- inactive"                    },
+    { EP_EXPLOSIVE,            "- explosive"                   },
+    { EP_FOOD_PENGUIN,         "- food for penguin"            },
+    { EP_PUSHABLE,             "- pushable"                    },
+    { EP_PLAYER,               "- player"                      },
+    { EP_HAS_CONTENT,          "- has content"                 },
+    { EP_DIGGABLE,             "- diggable"                    },
+    { EP_SP_ELEMENT,           "- SB style"                    },
+    { EP_WALKABLE_THROUGH,     "- walkable through"            },
+    { EP_OVER_PLAYER,          "- over player"                 },
+    { EP_ACTIVE_BOMB,          "- active bomb"                 },
+    { EP_BELT,                 "- belt"                        },
+    { EP_BELT_ACTIVE,          "- active belt"                 },
+    { EP_BELT_SWITCH,          "- belt switch"                 },
+    { EP_WALKABLE_UNDER,       "- walkable under"              },
+    { EP_EM_SLIPPERY_WALL,     "- EM style slippery wall"      },
+    { EP_CAN_BE_CRUMBLED,      "- can be crumbled"             },
+    { -1,                      NULL                            }
+  };
+  char *filename = getElementDescriptionFilename(properties_element);
+  char *percentage_text = "In this level:";
+  char *properties_text = "Standard properties:";
+  float percentage;
+  int num_elements_in_level;
+  int num_standard_properties = 0;
+  int font1_nr = FONT_TEXT_1;
+  int font2_nr = FONT_TEXT_2;
+  int font1_width = getFontWidth(font1_nr);
+  int font2_height = getFontHeight(font2_nr);
+  int pad_x = ED_SETTINGS_XPOS;
+  int pad_y = 5 * TILEY;
+  int screen_line = 2;
+  int i, x, y;
+
+  num_elements_in_level = 0;
+  for (y=0; y<lev_fieldy; y++) 
+    for (x=0; x<lev_fieldx; x++)
+      if (Feld[x][y] == properties_element)
+       num_elements_in_level++;
+  percentage = num_elements_in_level * 100.0 / (lev_fieldx * lev_fieldy);
+
+  DrawTextF(pad_x, pad_y, font1_nr, percentage_text);
+  DrawTextF(pad_x + strlen(percentage_text) * font1_width, pad_y,
+           font2_nr, "%d (%.2f%%)", num_elements_in_level, percentage);
+
+  for (i=0; properties[i].value != -1; i++)
+    if (HAS_PROPERTY(properties_element, properties[i].value))
+      num_standard_properties++;
+
+  if (num_standard_properties > 0)
+  {
+    DrawTextF(pad_x, pad_y + screen_line * font2_height, font1_nr,
+             properties_text);
+    screen_line++;
+
+    for (i=0; properties[i].value != -1; i++)
+    {
+      if (!HAS_PROPERTY(properties_element, properties[i].value))
+       continue;
+
+      DrawTextF(pad_x, pad_y + screen_line * font2_height, font2_nr,
+               properties[i].text);
+      screen_line++;
+    }
+
+    screen_line++;
   }
+
+  PrintInfoText("Description:", FONT_TEXT_1, screen_line);
+  if (PrintElementDescriptionFromFile(filename, screen_line + 1) == 0)
+    PrintInfoText("No description available.", FONT_TEXT_1, screen_line);
+}
+
+static void DrawPropertiesAdvanced()
+{
+  DrawText(SX + ED_SETTINGS_XPOS, SY + 5 * TILEY, "Coming soon!", FONT_TEXT_1);
+}
+
+static void DrawPropertiesWindow()
+{
+  int xstart = 2;
+  int ystart = 4;
+
+  /* make sure that previous properties edit mode exists for this element */
+  if (edit_mode_properties == ED_MODE_PROPERTIES_ADVANCED &&
+      !IS_CUSTOM_ELEMENT(properties_element))
+    edit_mode_properties = ED_MODE_PROPERTIES_CONFIG;
+
+  if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG &&
+      !checkPropertiesConfig())
+    edit_mode_properties = ED_MODE_PROPERTIES_INFO;
+
+  UnmapLevelEditorWindowGadgets();
+
+  SetMainBackgroundImage(IMG_BACKGROUND_EDITOR);
+  ClearWindow();
+
+  DrawText(SX + ED_SETTINGS2_XPOS, SY + ED_SETTINGS_YPOS,
+          "Element Settings", FONT_TITLE_1);
+
+  DrawElementBorder(SX + xstart * MINI_TILEX,
+                   SY + ystart * MINI_TILEY + MINI_TILEY / 2,
+                   TILEX, TILEY);
+  DrawGraphicAnimationExt(drawto,
+                         SX + xstart * MINI_TILEX,
+                         SY + ystart * MINI_TILEY + MINI_TILEY / 2,
+                         el2img(properties_element), -1, NO_MASKING);
+
+  FrameCounter = 0;    /* restart animation frame counter */
+
+  DrawTextF((xstart + 3) * MINI_TILEX, (ystart + 1) * MINI_TILEY,
+           FONT_TEXT_1, getElementInfoText(properties_element));
+
+  DrawPropertiesTabulatorGadgets();
+
+  if (edit_mode_properties == ED_MODE_PROPERTIES_INFO)
+    DrawPropertiesInfo();
+  else if (edit_mode_properties == ED_MODE_PROPERTIES_CONFIG)
+    DrawPropertiesConfig();
+  else /* edit_mode_properties == ED_MODE_PROPERTIES_ADVANCED */
+    DrawPropertiesAdvanced();
 }
 
 static void DrawLineElement(int sx, int sy, int element, boolean change_level)
@@ -3284,8 +3892,8 @@ static void DrawLine(int from_x, int from_y, int to_x, int to_y,
   }
 }
 
-static void DrawRectangle(int from_x, int from_y, int to_x, int to_y,
-                         int element, boolean change_level)
+static void DrawBox(int from_x, int from_y, int to_x, int to_y,
+                   int element, boolean change_level)
 {
   DrawLine(from_x, from_y, from_x, to_y, element, change_level);
   DrawLine(from_x, to_y, to_x, to_y, element, change_level);
@@ -3407,7 +4015,7 @@ static void SelectArea(int from_x, int from_y, int to_x, int to_y,
                       int element, boolean change_level)
 {
   if (element == -1 || change_level)
-    DrawRectangle(from_x, from_y, to_x, to_y, -1, FALSE);
+    DrawBox(from_x, from_y, to_x, to_y, -1, FALSE);
   else
     DrawAreaBorder(from_x, from_y, to_x, to_y);
 }
@@ -3595,11 +4203,11 @@ static int DrawLevelText(int sx, int sy, char letter, int mode)
   if (letter >= 'a' && letter <= 'z')
     letter_element = EL_CHAR_ASCII0 + letter + (int)('A' - 'a');
   else if (letter == 'ä' || letter == 'Ä')
-    letter_element = EL_CHAR_AE;
+    letter_element = EL_CHAR_AUMLAUT;
   else if (letter == 'ö' || letter == 'Ö')
-    letter_element = EL_CHAR_OE;
+    letter_element = EL_CHAR_OUMLAUT;
   else if (letter == 'ü' || letter == 'Ü')
-    letter_element = EL_CHAR_UE;
+    letter_element = EL_CHAR_UUMLAUT;
   else if (letter == '^')
     letter_element = EL_CHAR_COPYRIGHT;
   else
@@ -3941,6 +4549,13 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
 
        if (id == GADGET_ID_AMOEBA_CONTENT)
          level.amoeba_content = new_element;
+       else if (id == GADGET_ID_CUSTOM_CHANGED &&
+                IS_CUSTOM_ELEMENT(properties_element))
+       {
+         int i = properties_element - EL_CUSTOM_START;
+
+         level.custom_element_successor[i] = new_element;
+       }
        else if (id == GADGET_ID_RANDOM_BACKGROUND)
          random_placement_background_element = new_element;
        else if (id >= GADGET_ID_ELEM_CONTENT_0 &&
@@ -3987,7 +4602,7 @@ static void HandleDrawingAreas(struct GadgetInfo *gi)
        else if (drawing_function == GADGET_ID_ARC)
          draw_func = DrawArc;
        else if (drawing_function == GADGET_ID_RECTANGLE)
-         draw_func = DrawRectangle;
+         draw_func = DrawBox;
        else if (drawing_function == GADGET_ID_FILLED_BOX)
          draw_func = DrawFilledBox;
        else if (drawing_function == GADGET_ID_GRAB_BRUSH)
@@ -4114,6 +4729,30 @@ static void HandleTextInputGadgets(struct GadgetInfo *gi)
   strcpy(textinput_info[gi->custom_type_id].value, gi->text.value);
 }
 
+static void HandleSelectboxGadgets(struct GadgetInfo *gi)
+{
+  int type_id = gi->custom_type_id;
+
+  *selectbox_info[type_id].index = gi->selectbox.index;
+
+#if 0
+  printf("Selected text value: '%s' [%d]\n",
+        selectbox_info[type_id].options[gi->selectbox.index].text,
+        selectbox_info[type_id].options[gi->selectbox.index].value);
+#endif
+}
+
+static void HandleTextbuttonGadgets(struct GadgetInfo *gi)
+{
+  if (gi->custom_type_id >= ED_TEXTBUTTON_ID_PROPERTIES_INFO &&
+      gi->custom_type_id <= ED_TEXTBUTTON_ID_PROPERTIES_ADVANCED)
+  {
+    edit_mode_properties = gi->custom_type_id;
+
+    DrawPropertiesWindow();
+  }
+}
+
 static void HandleRadiobuttons(struct GadgetInfo *gi)
 {
   *radiobutton_info[gi->custom_type_id].value =
@@ -4128,7 +4767,7 @@ static void HandleCheckbuttons(struct GadgetInfo *gi)
 
   if (type_id >= ED_CHECKBUTTON_ID_CUSTOM_FIRST &&
       type_id <= ED_CHECKBUTTON_ID_CUSTOM_LAST)
-    CopyCustomElementPropertiesToGame();
+    CopyCustomElementPropertiesToGame(properties_element);
 }
 
 static void HandleControlButtons(struct GadgetInfo *gi)
@@ -4420,8 +5059,12 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 
        PickDrawingElement(button, new_element);
 
+#if 1
+       if (!stick_element_properties_window)
+#else
        if (!HAS_CONTENT(properties_element) ||
            !stick_element_properties_window)
+#endif
        {
          properties_element = new_element;
          if (edit_mode == ED_MODE_PROPERTIES)
@@ -4535,7 +5178,7 @@ void HandleLevelEditorIdle()
   DrawGraphicAnimationExt(drawto,
                          SX + xpos * TILEX,
                          SY + ypos * TILEY + MINI_TILEY / 2,
-                         el2edimg(properties_element), -1, NO_MASKING);
+                         el2img(properties_element), -1, NO_MASKING);
 
   MarkTileDirty(xpos, ypos);
   MarkTileDirty(xpos, ypos + 1);
@@ -4713,6 +5356,9 @@ static void HandleDrawingAreaInfo(struct GadgetInfo *gi)
   else if (id == GADGET_ID_AMOEBA_CONTENT)
     DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
              "Amoeba content");
+  else if (id == GADGET_ID_CUSTOM_CHANGED)
+    DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
+             "Next element after change");
   else if (id == GADGET_ID_RANDOM_BACKGROUND)
     DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FONT_TEXT_2,
              "Random placement background");