added configurability of editor control buttons (toolbox buttons)
[rocksndiamonds.git] / src / editor.c
index 206d1c1df6d0b00d5525ffdd938da0c0007a4098..6a95010a354f054ba20386ed8e4b398cbc6de469 100644 (file)
   -----------------------------------------------------------------------------
 */
 
-/* positions in the level editor */
-#define ED_WIN_MB_LEFT_XPOS            (editor.palette.element_left.x)
-#define ED_WIN_MB_LEFT_YPOS            (editor.palette.element_left.y)
-#define ED_WIN_MB_MIDDLE_XPOS          (editor.palette.element_middle.x)
-#define ED_WIN_MB_MIDDLE_YPOS          (editor.palette.element_middle.y)
-#define ED_WIN_MB_RIGHT_XPOS           (editor.palette.element_right.x)
-#define ED_WIN_MB_RIGHT_YPOS           (editor.palette.element_right.y)
-
 /* values for the control window */
-#define ED_CTRL_NO_BUTTONS_GFX_XPOS    6
-#define ED_CTRL_NO_BUTTONS_GFX_YPOS    286
-#define ED_CTRL1_BUTTONS_GFX_YPOS      236
-#define ED_CTRL2_BUTTONS_GFX_YPOS      236
-#define ED_CTRL3_BUTTONS_GFX_YPOS      324
-#define ED_CTRL4_BUTTONS_GFX_XPOS      44
-#define ED_CTRL4_BUTTONS_GFX_YPOS      214
-#define ED_CTRL1_BUTTONS_ALT_GFX_YPOS  142
-#define ED_CTRL3_BUTTONS_ALT_GFX_YPOS  302
-
-#define ED_CTRL1_BUTTON_XSIZE          22
-#define ED_CTRL1_BUTTON_YSIZE          22
-#define ED_CTRL1_BUTTONS_XPOS          6
-#define ED_CTRL1_BUTTONS_YPOS          6
-#define ED_CTRL2_BUTTON_XSIZE          30
-#define ED_CTRL2_BUTTON_YSIZE          20
-#define ED_CTRL2_BUTTONS_XPOS          5
-#define ED_CTRL2_BUTTONS_YPOS          99
-#define ED_CTRL3_BUTTON_XSIZE          22
-#define ED_CTRL3_BUTTON_YSIZE          22
-#define ED_CTRL3_BUTTONS_XPOS          6
-#define ED_CTRL3_BUTTONS_YPOS          6
-#define ED_CTRL4_BUTTON_XSIZE          22
-#define ED_CTRL4_BUTTON_YSIZE          22
-#define ED_CTRL4_BUTTONS_XPOS          6
-#define ED_CTRL4_BUTTONS_YPOS          6
-
 #define ED_CTRL1_BUTTONS_HORIZ         4
 #define ED_CTRL1_BUTTONS_VERT          4
 #define ED_CTRL2_BUTTONS_HORIZ         3
 #define ED_CTRL3_BUTTONS_VERT          1
 #define ED_CTRL4_BUTTONS_HORIZ         2
 #define ED_CTRL4_BUTTONS_VERT          1
+#define ED_CTRL5_BUTTONS_HORIZ         1
+#define ED_CTRL5_BUTTONS_VERT          1
 
 #define ED_NUM_CTRL1_BUTTONS   (ED_CTRL1_BUTTONS_HORIZ * ED_CTRL1_BUTTONS_VERT)
 #define ED_NUM_CTRL2_BUTTONS   (ED_CTRL2_BUTTONS_HORIZ * ED_CTRL2_BUTTONS_VERT)
 #define ED_NUM_CTRL3_BUTTONS   (ED_CTRL3_BUTTONS_HORIZ * ED_CTRL3_BUTTONS_VERT)
 #define ED_NUM_CTRL4_BUTTONS   (ED_CTRL4_BUTTONS_HORIZ * ED_CTRL4_BUTTONS_VERT)
+#define ED_NUM_CTRL5_BUTTONS   (ED_CTRL5_BUTTONS_HORIZ * ED_CTRL5_BUTTONS_VERT)
 #define ED_NUM_CTRL1_2_BUTTONS (ED_NUM_CTRL1_BUTTONS   + ED_NUM_CTRL2_BUTTONS)
 #define ED_NUM_CTRL1_3_BUTTONS (ED_NUM_CTRL1_2_BUTTONS + ED_NUM_CTRL3_BUTTONS)
-#define ED_NUM_CTRL_BUTTONS    (ED_NUM_CTRL1_BUTTONS + \
-                               ED_NUM_CTRL2_BUTTONS +  \
-                               ED_NUM_CTRL3_BUTTONS +  \
-                               ED_NUM_CTRL4_BUTTONS)
+#define ED_NUM_CTRL1_4_BUTTONS (ED_NUM_CTRL1_3_BUTTONS + ED_NUM_CTRL4_BUTTONS)
+#define ED_NUM_CTRL_BUTTONS    (ED_NUM_CTRL1_4_BUTTONS + ED_NUM_CTRL5_BUTTONS)
 
 /* values for the element list */
 #define ED_ELEMENTLIST_XPOS            (editor.palette.x)
 #define ED_ELEMENTLIST_YPOS            (editor.palette.y)
-#define ED_ELEMENTLIST_XSIZE           20
-#define ED_ELEMENTLIST_YSIZE           20
+#define ED_ELEMENTLIST_XSIZE           (graphic_info[IMG_EDITOR_PALETTE_BUTTON].width)
+#define ED_ELEMENTLIST_YSIZE           (graphic_info[IMG_EDITOR_PALETTE_BUTTON].height)
 #define ED_ELEMENTLIST_BUTTONS_HORIZ   (editor.palette.cols)
 #define ED_ELEMENTLIST_BUTTONS_VERT    (editor.palette.rows)
 #define ED_NUM_ELEMENTLIST_BUTTONS     (ED_ELEMENTLIST_BUTTONS_HORIZ * \
 #define ED_SCROLLBAR2_XPOS             50
 #define ED_SCROLLBAR2_YPOS             20
 
-#define ED_SCROLLBUTTON2_XSIZE         10
-#define ED_SCROLLBUTTON2_YSIZE         10
+#define ED_SCROLLBUTTON2_XSIZE         (graphic_info[IMG_EDITOR_PALETTE_SCROLL_UP].width)
+#define ED_SCROLLBUTTON2_YSIZE         (graphic_info[IMG_EDITOR_PALETTE_SCROLL_UP].height)
 
 #define ED_SCROLL2_UP_XPOS             (ED_ELEMENTLIST_XPOS +          \
                                         ED_ELEMENTLIST_BUTTONS_HORIZ * \
 #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 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_ZOOM                 (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_CUSTOM_COPY          (GADGET_ID_TOOLBOX_FIRST + 25)
 #define GADGET_ID_CUSTOM_PASTE         (GADGET_ID_TOOLBOX_FIRST + 26)
 
+#define GADGET_ID_PROPERTIES           (GADGET_ID_TOOLBOX_FIRST + 27)
+
 /* counter gadget identifiers */
-#define GADGET_ID_COUNTER_FIRST                (GADGET_ID_TOOLBOX_FIRST + 27)
+#define GADGET_ID_COUNTER_FIRST                (GADGET_ID_TOOLBOX_FIRST + 28)
 
 #define GADGET_ID_SELECT_LEVEL_DOWN    (GADGET_ID_COUNTER_FIRST + 0)
 #define GADGET_ID_SELECT_LEVEL_TEXT    (GADGET_ID_COUNTER_FIRST + 1)
 
 static struct
 {
+  int graphic;
+  int gadget_id;
+  struct XY *pos;
+  int gadget_type;
+  char *infotext;
   char shortcut;
-  char *text;
-} control_info[ED_NUM_CTRL_BUTTONS] =
+} controlbutton_info[ED_NUM_CTRL_BUTTONS] =
 {
   /* note: some additional characters are already reserved for "cheat mode"
      shortcuts (":XYZ" style) -- for details, see "events.c" */
 
-  { 's',       "draw single items"                     },
-  { 'd',       "draw connected items"                  },
-  { 'l',       "draw lines"                            },
-  { 'a',       "draw arcs"                             },
-  { 'r',       "draw outline rectangles"               },
-  { 'R',       "draw filled rectangles"                },
-  { '\0',      "wrap (rotate) level up"                },
-  { 't',       "enter text elements"                   },
-  { 'f',       "flood fill"                            },
-  { '\0',      "wrap (rotate) level left"              },
-  { '?',       "properties of drawing element"         },
-  { '\0',      "wrap (rotate) level right"             },
-  { '\0',      "random element placement"              },
-  { 'b',       "grab brush"                            },
-  { '\0',      "wrap (rotate) level down"              },
-  { ',',       "pick drawing element"                  },
-
-  { 'U',       "undo last operation"                   },
-  { 'I',       "properties of level"                   },
-  { 'S',       "save level"                            },
-  { 'C',       "clear level"                           },
-  { 'T',       "test level"                            },
-  { 'E',       "exit level editor"                     },
-
-  { '\0',      "copy settings from other element"      },
-  { '\0',      "copy settings to other element"        },
-  { '\0',      "exchange element with other element"   },
-
-  { '\0',      "copy settings from this element"       },
-  { '\0',      "paste settings to this element"        },
+  /* ---------- toolbox control buttons ------------------------------------ */
+
+  {
+    IMG_EDITOR_BUTTON_GFX_DRAW_SINGLE,         GADGET_ID_SINGLE_ITEMS,
+    &editor.button.draw_single,                        GD_TYPE_RADIO_BUTTON,
+    "draw single items",                       's'
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_DRAW_CONNECTED,      GADGET_ID_CONNECTED_ITEMS,
+    &editor.button.draw_connected,             GD_TYPE_RADIO_BUTTON,
+    "draw connected items",                    'd'
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_DRAW_LINE,           GADGET_ID_LINE,
+    &editor.button.draw_line,                  GD_TYPE_RADIO_BUTTON,
+    "draw lines",                              'l'
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_DRAW_ARC,            GADGET_ID_ARC,
+    &editor.button.draw_arc,                   GD_TYPE_RADIO_BUTTON,
+    "draw arcs",                               'a'
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_DRAW_RECTANGLE,      GADGET_ID_RECTANGLE,
+    &editor.button.draw_rectangle,             GD_TYPE_RADIO_BUTTON,
+    "draw outline rectangles",                 'r'
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_DRAW_FILLED_BOX,     GADGET_ID_FILLED_BOX,
+    &editor.button.draw_filled_box,            GD_TYPE_RADIO_BUTTON,
+    "draw filled rectangles",                  'R'
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_ROTATE_UP,           GADGET_ID_WRAP_UP,
+    &editor.button.rotate_up,                  GD_TYPE_NORMAL_BUTTON,
+    "wrap (rotate) level up",                  0
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_DRAW_TEXT,           GADGET_ID_TEXT,
+    &editor.button.draw_text,                  GD_TYPE_RADIO_BUTTON,
+    "enter text elements",                     't'
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_FLOOD_FILL,          GADGET_ID_FLOOD_FILL,
+    &editor.button.flood_fill,                 GD_TYPE_RADIO_BUTTON,
+    "flood fill",                              'f'
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_ROTATE_LEFT,         GADGET_ID_WRAP_LEFT,
+    &editor.button.rotate_left,                        GD_TYPE_NORMAL_BUTTON,
+    "wrap (rotate) level left",                        0
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_ZOOM_LEVEL,          GADGET_ID_ZOOM,
+    &editor.button.zoom_level,                 GD_TYPE_NORMAL_BUTTON,
+    "zoom level tile size",                    'z'
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_ROTATE_RIGHT,                GADGET_ID_WRAP_RIGHT,
+    &editor.button.rotate_right,               GD_TYPE_NORMAL_BUTTON,
+    "wrap (rotate) level right",               0
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_DRAW_RANDOM,         GADGET_ID_RANDOM_PLACEMENT,
+    &editor.button.draw_random,                        GD_TYPE_NORMAL_BUTTON,
+    "random element placement",                        0
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_GRAB_BRUSH,          GADGET_ID_GRAB_BRUSH,
+    &editor.button.grab_brush,                 GD_TYPE_RADIO_BUTTON,
+    "grab brush",                              'b'
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_ROTATE_DOWN,         GADGET_ID_WRAP_DOWN,
+    &editor.button.rotate_down,                        GD_TYPE_NORMAL_BUTTON,
+    "wrap (rotate) level down",                        0
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_PICK_ELEMENT,                GADGET_ID_PICK_ELEMENT,
+    &editor.button.pick_element,               GD_TYPE_RADIO_BUTTON,
+    "pick drawing element",                    ','
+  },
+
+  /* ---------- level control buttons -------------------------------------- */
+
+  {
+    IMG_EDITOR_BUTTON_GFX_UNDO,                        GADGET_ID_UNDO,
+    &editor.button.undo,                       GD_TYPE_NORMAL_BUTTON,
+    "undo last operation",                     'U'
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_CONF,                        GADGET_ID_INFO,
+    &editor.button.conf,                       GD_TYPE_NORMAL_BUTTON,
+    "properties of level",                     'I'
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_SAVE,                        GADGET_ID_SAVE,
+    &editor.button.save,                       GD_TYPE_NORMAL_BUTTON,
+    "save level",                              'S'
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_CLEAR,               GADGET_ID_CLEAR,
+    &editor.button.clear,                      GD_TYPE_NORMAL_BUTTON,
+    "clear level",                             'C'
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_TEST,                        GADGET_ID_TEST,
+    &editor.button.test,                       GD_TYPE_NORMAL_BUTTON,
+    "test level",                              'T'
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_EXIT,                        GADGET_ID_EXIT,
+    &editor.button.exit,                       GD_TYPE_NORMAL_BUTTON,
+    "exit level editor",                       'E'
+  },
+
+  /* ---------- CE and GE control buttons ---------------------------------- */
+
+  {
+    IMG_EDITOR_BUTTON_GFX_CE_COPY_FROM,                GADGET_ID_CUSTOM_COPY_FROM,
+    &editor.button.ce_copy_from,               GD_TYPE_RADIO_BUTTON,
+    "copy settings from other element",                0
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_CE_COPY_TO,          GADGET_ID_CUSTOM_COPY_TO,
+    &editor.button.ce_copy_to,                 GD_TYPE_RADIO_BUTTON,
+    "copy settings to other element",          0
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_CE_SWAP,             GADGET_ID_CUSTOM_EXCHANGE,
+    &editor.button.ce_swap,                    GD_TYPE_RADIO_BUTTON,
+    "exchange element with other element",     0
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_CE_COPY,             GADGET_ID_CUSTOM_COPY,
+    &editor.button.ce_copy,                    GD_TYPE_NORMAL_BUTTON,
+    "copy settings from this element",         0
+  },
+  {
+    IMG_EDITOR_BUTTON_GFX_CE_PASTE,            GADGET_ID_CUSTOM_PASTE,
+    &editor.button.ce_paste,                   GD_TYPE_NORMAL_BUTTON,
+    "paste settings to this element",          0
+  },
+
+  /* ---------- palette control buttons ------------------------------------ */
+
+  {
+    IMG_EDITOR_BUTTON_GFX_PROPERTIES,          GADGET_ID_PROPERTIES,
+    &editor.button.properties,                 GD_TYPE_NORMAL_BUTTON,
+    "properties of drawing element",           'p'
+  }
 };
 
 static int random_placement_value = 10;
@@ -3999,13 +4088,13 @@ static int editor_el_chars[] =
   EL_CHAR('^'),
   EL_CHAR('_'),
 
-  EL_CHAR('©'),
-  EL_CHAR('Ä'),
-  EL_CHAR('Ö'),
-  EL_CHAR('Ü'),
+  EL_CHAR(CHAR_BYTE_COPYRIGHT),
+  EL_CHAR(CHAR_BYTE_UMLAUT_A),
+  EL_CHAR(CHAR_BYTE_UMLAUT_O),
+  EL_CHAR(CHAR_BYTE_UMLAUT_U),
 
-  EL_CHAR('°'),
-  EL_CHAR('®'),
+  EL_CHAR(CHAR_BYTE_DEGREE),
+  EL_CHAR(CHAR_BYTE_REGISTERED),
   EL_CHAR(FONT_ASCII_CURSOR),
   EL_CHAR(FONT_ASCII_BUTTON),
 
@@ -4109,13 +4198,13 @@ static int editor_el_steel_chars[] =
   EL_STEEL_CHAR('^'),
   EL_STEEL_CHAR('_'),
 
-  EL_STEEL_CHAR('©'),
-  EL_STEEL_CHAR('Ä'),
-  EL_STEEL_CHAR('Ö'),
-  EL_STEEL_CHAR('Ü'),
+  EL_STEEL_CHAR(CHAR_BYTE_COPYRIGHT),
+  EL_STEEL_CHAR(CHAR_BYTE_UMLAUT_A),
+  EL_STEEL_CHAR(CHAR_BYTE_UMLAUT_O),
+  EL_STEEL_CHAR(CHAR_BYTE_UMLAUT_U),
 
-  EL_STEEL_CHAR('°'),
-  EL_STEEL_CHAR('®'),
+  EL_STEEL_CHAR(CHAR_BYTE_DEGREE),
+  EL_STEEL_CHAR(CHAR_BYTE_REGISTERED),
   EL_STEEL_CHAR(FONT_ASCII_CURSOR),
   EL_STEEL_CHAR(FONT_ASCII_BUTTON),
 
@@ -4788,27 +4877,47 @@ static char *getElementInfoText(int element)
   return info_text;
 }
 
-char *getElementDescriptionFilename(int element)
+static char *getElementDescriptionFilenameExt(char *basename)
 {
-  char *docs_dir = options.docs_directory;
   char *elements_subdir = "elements";
+  static char *elements_subdir2 = NULL;
   static char *filename = NULL;
-  char basename[MAX_FILENAME_LEN];
+
+  if (elements_subdir2 == NULL)
+    elements_subdir2 = getPath2(DOCS_DIRECTORY, elements_subdir);
 
   checked_free(filename);
 
-  /* 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);
+  /* 1st try: look for element description in current level set directory */
+  filename = getPath3(getCurrentLevelDir(), elements_subdir2, basename);
   if (fileExists(filename))
     return filename;
 
   free(filename);
 
+  /* 2nd try: look for element description in the game's base directory */
+  filename = getPath3(options.docs_directory, elements_subdir, basename);
+  if (fileExists(filename))
+    return filename;
+
+  return NULL;
+}
+
+char *getElementDescriptionFilename(int element)
+{
+  char basename[MAX_FILENAME_LEN];
+  char *filename;
+
+  /* 1st try: look for element description file for exactly this element */
+  sprintf(basename, "%s.txt", element_info[element].token_name);
+  filename = getElementDescriptionFilenameExt(basename);
+  if (filename != NULL)
+    return filename;
+
   /* 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))
+  filename = getElementDescriptionFilenameExt(basename);
+  if (filename != NULL)
     return filename;
 
   return NULL;
@@ -4927,7 +5036,9 @@ static void ReinitializeElementList()
     {
       if (setup.editor.el_headlines)
       {
-       num_editor_elements += *editor_elements_info[i].headline_list_size;
+       // required for correct padding of palette headline buttons
+       if (*editor_elements_info[i].headline_list_size > 0)
+         num_editor_elements += editor.palette.cols;
 
        for (j = 0; j < *editor_elements_info[i].headline_list_size; j++)
        {
@@ -4941,7 +5052,13 @@ static void ReinitializeElementList()
       if (found_inactive_cascade)
        continue;
 
-      num_editor_elements += *editor_elements_info[i].element_list_size;
+      // required for correct padding of palette element buttons
+      int element_list_size = *editor_elements_info[i].element_list_size;
+      int element_rows =
+       (element_list_size + editor.palette.cols - 1) / editor.palette.cols;
+      int element_buttons = editor.palette.cols * element_rows;
+
+      num_editor_elements += element_buttons;
     }
   }
 
@@ -4965,9 +5082,16 @@ static void ReinitializeElementList()
     {
       if (setup.editor.el_headlines)
       {
-       for (j = 0; j < *editor_elements_info[i].headline_list_size; j++)
+       // required for correct padding of palette headline buttons
+       int headline_size = (*editor_elements_info[i].headline_list_size > 0 ?
+                            editor.palette.cols : 0);
+
+       for (j = 0; j < headline_size; j++)
        {
-         int element = (*editor_elements_info[i].headline_list)[j];
+         // use empty elements for padding of palette headline buttons
+         int element = (j < *editor_elements_info[i].headline_list_size ?
+                        (*editor_elements_info[i].headline_list)[j] :
+                        editor_el_empty[0]);
 
          editor_elements[pos++] = element;
 
@@ -4979,8 +5103,19 @@ static void ReinitializeElementList()
       if (found_inactive_cascade)
        continue;
 
-      for (j = 0; j < *editor_elements_info[i].element_list_size; j++)
+      // required for correct padding of palette element buttons
+      int element_list_size = *editor_elements_info[i].element_list_size;
+      int element_rows =
+       (element_list_size + editor.palette.cols - 1) / editor.palette.cols;
+      int element_buttons = editor.palette.cols * element_rows;
+
+      // copy all elements from element list
+      for (j = 0; j < element_list_size; j++)
        editor_elements[pos++] = (*editor_elements_info[i].element_list)[j];
+
+      // use empty elements for padding of palette element buttons
+      for (j = 0; j < element_buttons - element_list_size; j++)
+       editor_elements[pos++] = editor_el_empty[0];
     }
   }
 
@@ -5155,49 +5290,55 @@ static void ScrollMiniLevel(int from_x, int from_y, int scroll)
   BackToFront();
 }
 
+void getElementListGraphicSource(int element, Bitmap **bitmap, int *x, int *y)
+{
+  int graphic = el2edimg(element);
+  int tile_size = (editor.palette.tile_size >= TILESIZE ? TILESIZE :
+                  MINI_TILESIZE);
+
+  getSizedGraphicSource(graphic, 0, tile_size, bitmap, x, y);
+}
+
 static void CreateControlButtons()
 {
-  Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
   struct GadgetInfo *gi;
-  unsigned int event_mask;
   int i;
 
   /* create toolbox buttons */
   for (i = 0; i < ED_NUM_CTRL_BUTTONS; i++)
   {
-    int id = i;
-    int width, height;
-    int gd_xoffset, gd_yoffset;
-    int gd_x1, gd_x2, gd_y1, gd_y2;
-    int button_type;
-    int radio_button_nr;
-    boolean checked;
-
-    if (id == GADGET_ID_SINGLE_ITEMS ||
-       id == GADGET_ID_CONNECTED_ITEMS ||
-       id == GADGET_ID_LINE ||
-       id == GADGET_ID_ARC ||
-       id == GADGET_ID_TEXT ||
-       id == GADGET_ID_RECTANGLE ||
-       id == GADGET_ID_FILLED_BOX ||
-       id == GADGET_ID_FLOOD_FILL ||
-       id == GADGET_ID_GRAB_BRUSH ||
-       id == GADGET_ID_PICK_ELEMENT ||
-       id == GADGET_ID_CUSTOM_COPY_FROM ||
-       id == GADGET_ID_CUSTOM_COPY_TO ||
-       id == GADGET_ID_CUSTOM_EXCHANGE)
+    int id = controlbutton_info[i].gadget_id;
+    int type = controlbutton_info[i].gadget_type;
+    int graphic = controlbutton_info[i].graphic;
+    struct XY *pos = controlbutton_info[i].pos;
+    struct GraphicInfo *gd = &graphic_info[graphic];
+    Bitmap *gd_bitmap = gd->bitmap;
+    int gd_x1 = gd->src_x;
+    int gd_y1 = gd->src_y;
+    int gd_x2 = gd->src_x + gd->pressed_xoffset;
+    int gd_y2 = gd->src_y + gd->pressed_yoffset;
+    int gd_x1a = gd->src_x + gd->active_xoffset;
+    int gd_y1a = gd->src_y + gd->active_yoffset;
+    int gd_x2a = gd->src_x + gd->active_xoffset + gd->pressed_xoffset;
+    int gd_y2a = gd->src_y + gd->active_yoffset + gd->pressed_yoffset;
+    int width  = gd->width;
+    int height = gd->height;
+    int x = pos->x;
+    int y = pos->y;
+    unsigned int event_mask;
+    int radio_button_nr = RADIO_NR_NONE;
+    boolean checked = FALSE;
+
+    if (type == GD_TYPE_RADIO_BUTTON)
     {
-      button_type = GD_TYPE_RADIO_BUTTON;
-      radio_button_nr = RADIO_NR_DRAWING_TOOLBOX;
-      checked = (id == drawing_function ? TRUE : FALSE);
       event_mask = GD_EVENT_PRESSED;
+      radio_button_nr = RADIO_NR_DRAWING_TOOLBOX;
+
+      if (id == drawing_function)
+       checked = TRUE;
     }
     else
     {
-      button_type = GD_TYPE_NORMAL_BUTTON;
-      radio_button_nr = RADIO_NR_NONE;
-      checked = FALSE;
-
       if (id == GADGET_ID_WRAP_LEFT ||
          id == GADGET_ID_WRAP_RIGHT ||
          id == GADGET_ID_WRAP_UP ||
@@ -5207,82 +5348,32 @@ static void CreateControlButtons()
        event_mask = GD_EVENT_RELEASED;
     }
 
-    if (id < ED_NUM_CTRL1_BUTTONS)
+    if (id == GADGET_ID_PROPERTIES)
     {
-      int x = i % ED_CTRL1_BUTTONS_HORIZ;
-      int y = i / ED_CTRL1_BUTTONS_HORIZ;
-
-      gd_xoffset = ED_CTRL1_BUTTONS_XPOS + x * ED_CTRL1_BUTTON_XSIZE;
-      gd_yoffset = ED_CTRL1_BUTTONS_YPOS + y * ED_CTRL1_BUTTON_YSIZE;
-      width  = ED_CTRL1_BUTTON_XSIZE;
-      height = ED_CTRL1_BUTTON_YSIZE;
-
-      gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
-      gd_x2 = DOOR_GFX_PAGEX7 + gd_xoffset;
-      gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL1_BUTTONS_GFX_YPOS     + gd_yoffset;
-      gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL1_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
-    }
-    else if (id < ED_NUM_CTRL1_2_BUTTONS)
-    {
-      int x = (i - ED_NUM_CTRL1_BUTTONS) % ED_CTRL2_BUTTONS_HORIZ;
-      int y = (i - ED_NUM_CTRL1_BUTTONS) / ED_CTRL2_BUTTONS_HORIZ;
-
-      gd_xoffset = ED_CTRL2_BUTTONS_XPOS + x * ED_CTRL2_BUTTON_XSIZE;
-      gd_yoffset = ED_CTRL2_BUTTONS_YPOS + y * ED_CTRL2_BUTTON_YSIZE;
-      width  = ED_CTRL2_BUTTON_XSIZE;
-      height = ED_CTRL2_BUTTON_YSIZE;
-
-      gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
-      gd_x2 = DOOR_GFX_PAGEX7 + gd_xoffset;
-      gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL2_BUTTONS_GFX_YPOS + gd_yoffset;
-      gd_y2 = 0;       /* no alternative graphic for these buttons */
-    }
-    else if (id < ED_NUM_CTRL1_3_BUTTONS)
-    {
-      int x = (i - ED_NUM_CTRL1_2_BUTTONS) % ED_CTRL3_BUTTONS_HORIZ + 1;
-      int y = (i - ED_NUM_CTRL1_2_BUTTONS) / ED_CTRL3_BUTTONS_HORIZ;
-
-      gd_xoffset = ED_CTRL3_BUTTONS_XPOS + x * ED_CTRL3_BUTTON_XSIZE;
-      gd_yoffset = ED_CTRL3_BUTTONS_YPOS + y * ED_CTRL3_BUTTON_YSIZE;
-      width  = ED_CTRL3_BUTTON_XSIZE;
-      height = ED_CTRL3_BUTTON_YSIZE;
-
-      gd_x1 = DOOR_GFX_PAGEX6 + gd_xoffset;
-      gd_x2 = DOOR_GFX_PAGEX5 + gd_xoffset;
-      gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL3_BUTTONS_GFX_YPOS     + gd_yoffset;
-      gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL3_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
+      x += DX;
+      y += DY;
     }
     else
     {
-      int x = (i - ED_NUM_CTRL1_3_BUTTONS) % ED_CTRL4_BUTTONS_HORIZ;
-      int y = (i - ED_NUM_CTRL1_3_BUTTONS) / ED_CTRL4_BUTTONS_HORIZ + 3;
-
-      gd_xoffset = ED_CTRL4_BUTTONS_XPOS + x * ED_CTRL4_BUTTON_XSIZE;
-      gd_yoffset = ED_CTRL4_BUTTONS_YPOS + y * ED_CTRL4_BUTTON_YSIZE;
-      width  = ED_CTRL4_BUTTON_XSIZE;
-      height = ED_CTRL4_BUTTON_YSIZE;
-
-      gd_x1 = DOOR_GFX_PAGEX6 + ED_CTRL4_BUTTONS_GFX_XPOS + gd_xoffset;
-      gd_x2 = DOOR_GFX_PAGEX5 + ED_CTRL4_BUTTONS_GFX_XPOS + gd_xoffset;
-      gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL4_BUTTONS_GFX_YPOS + gd_yoffset;
-      gd_y2 = 0;       /* no alternative graphic for these buttons */
+      x += EX;
+      y += EY;
     }
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
                      GDI_CUSTOM_TYPE_ID, i,
-                     GDI_INFO_TEXT, control_info[i].text,
-                     GDI_X, EX + gd_xoffset,
-                     GDI_Y, EY + gd_yoffset,
+                     GDI_INFO_TEXT, controlbutton_info[i].infotext,
+                     GDI_X, x,
+                     GDI_Y, y,
                      GDI_WIDTH, width,
                      GDI_HEIGHT, height,
-                     GDI_TYPE, button_type,
+                     GDI_TYPE, type,
                      GDI_STATE, GD_BUTTON_UNPRESSED,
                      GDI_RADIO_NR, radio_button_nr,
                      GDI_CHECKED, checked,
                      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_ALT_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
+                     GDI_ALT_DESIGN_UNPRESSED, gd_bitmap, gd_x1a, gd_y1a,
+                     GDI_ALT_DESIGN_PRESSED, gd_bitmap, gd_x2a, gd_y2a,
                      GDI_EVENT_MASK, event_mask,
                      GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
                      GDI_CALLBACK_ACTION, HandleControlButtons,
@@ -5314,36 +5405,27 @@ static void CreateControlButtons()
     int id = scrollbutton_info[i].gadget_id;
     int graphic = scrollbutton_info[i].graphic;
     struct GraphicInfo *gd = &graphic_info[graphic];
-    int x, y, width, height;
-    int gd_x1, gd_x2, gd_y1, gd_y2;
-
-    x = scrollbutton_pos[i].x;
-    y = scrollbutton_pos[i].y;
-
-    event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
+    Bitmap *gd_bitmap = gd->bitmap;
+    int gd_x1 = gd->src_x;
+    int gd_y1 = gd->src_y;
+    int gd_x2 = gd->src_x + gd->pressed_xoffset;
+    int gd_y2 = gd->src_y + gd->pressed_yoffset;
+    int width  = gd->width;
+    int height = gd->height;
+    int x = scrollbutton_pos[i].x;
+    int y = scrollbutton_pos[i].y;
+    unsigned int event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
 
     if (id == GADGET_ID_SCROLL_LIST_UP ||
        id == GADGET_ID_SCROLL_LIST_DOWN)
     {
       x += DX;
       y += DY;
-      width  = gd->width;
-      height = gd->height;
-      gd_x1 = gd->src_x;
-      gd_y1 = gd->src_y;
-      gd_x2 = gd->src_x + gd->pressed_xoffset;
-      gd_y2 = gd->src_y + gd->pressed_yoffset;
     }
     else
     {
       x += SX;
       y += SY;
-      width  = gd->width;
-      height = gd->height;
-      gd_x1 = gd->src_x;
-      gd_y1 = gd->src_y;
-      gd_x2 = gd->src_x + gd->pressed_xoffset;
-      gd_y2 = gd->src_y + gd->pressed_yoffset;
     }
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
@@ -5371,44 +5453,43 @@ static void CreateControlButtons()
   /* create buttons for element list */
   for (i = 0; i < ED_NUM_ELEMENTLIST_BUTTONS; i++)
   {
-    struct GraphicInfo *gd = &graphic_info[IMG_EDITOR_PALETTE_BUTTON];
+    int id = GADGET_ID_ELEMENTLIST_FIRST + i;
+    int graphic = IMG_EDITOR_PALETTE_BUTTON;
+    struct GraphicInfo *gd = &graphic_info[graphic];
+    Bitmap *gd_bitmap = gd->bitmap;
     Bitmap *deco_bitmap;
     int deco_x, deco_y, deco_xpos, deco_ypos;
-    int gd_xoffset, gd_yoffset;
-    int gd_x1, gd_y1, gd_x2, gd_y2;
-    int x = i % ED_ELEMENTLIST_BUTTONS_HORIZ;
-    int y = i / ED_ELEMENTLIST_BUTTONS_HORIZ;
-    int id = GADGET_ID_ELEMENTLIST_FIRST + i;
+    int gd_x1 = gd->src_x;
+    int gd_y1 = gd->src_y;
+    int gd_x2 = gd->src_x + gd->pressed_xoffset;
+    int gd_y2 = gd->src_y + gd->pressed_yoffset;
+    int xx = i % ED_ELEMENTLIST_BUTTONS_HORIZ;
+    int yy = i / ED_ELEMENTLIST_BUTTONS_HORIZ;
+    int x = DX + ED_ELEMENTLIST_XPOS + xx * gd->width;
+    int y = DY + ED_ELEMENTLIST_YPOS + yy * gd->height;
     int element = editor_elements[i];
+    int tile_size = (editor.palette.tile_size >= TILESIZE ? TILESIZE :
+                    MINI_TILESIZE);
+    unsigned int event_mask = GD_EVENT_RELEASED;
 
-    event_mask = GD_EVENT_RELEASED;
-
-    gd_xoffset = ED_ELEMENTLIST_XPOS + x * gd->width;
-    gd_yoffset = ED_ELEMENTLIST_YPOS + y * gd->height;
-
-    gd_x1 = gd->src_x;
-    gd_y1 = gd->src_y;
-    gd_x2 = gd->src_x + gd->pressed_xoffset;
-    gd_y2 = gd->src_y + gd->pressed_yoffset;
-
-    getMiniGraphicSource(el2edimg(element), &deco_bitmap, &deco_x, &deco_y);
-    deco_xpos = (gd->width  - MINI_TILEX) / 2;
-    deco_ypos = (gd->height - MINI_TILEY) / 2;
+    getElementListGraphicSource(element, &deco_bitmap, &deco_x, &deco_y);
+    deco_xpos = (gd->width  - tile_size) / 2;
+    deco_ypos = (gd->height - tile_size) / 2;
 
     gi = CreateGadget(GDI_CUSTOM_ID, id,
                      GDI_CUSTOM_TYPE_ID, i,
                      GDI_INFO_TEXT, getElementInfoText(element),
-                     GDI_X, DX + gd_xoffset,
-                     GDI_Y, DY + gd_yoffset,
+                     GDI_X, x,
+                     GDI_Y, y,
                      GDI_WIDTH, gd->width,
                      GDI_HEIGHT, gd->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_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
+                     GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
                      GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y,
                      GDI_DECORATION_POSITION, deco_xpos, deco_ypos,
-                     GDI_DECORATION_SIZE, MINI_TILEX, MINI_TILEY,
+                     GDI_DECORATION_SIZE, tile_size, tile_size,
                      GDI_DECORATION_SHIFTING, 1, 1,
                      GDI_EVENT_MASK, event_mask,
                      GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
@@ -5427,10 +5508,6 @@ static void CreateCounterButtons()
   int max_infotext_len = getMaxInfoTextLength();
   int i;
 
-  /* these values are not constant, but can change at runtime */
-  counterbutton_info[ED_COUNTER_ID_SELECT_LEVEL].x = DX + 5 - SX;
-  counterbutton_info[ED_COUNTER_ID_SELECT_LEVEL].y = DY + 3 - SY;
-
   for (i = 0; i < ED_NUM_COUNTERBUTTONS; i++)
   {
     int j;
@@ -5472,9 +5549,16 @@ static void CreateCounterButtons()
 
        event_mask |= GD_EVENT_RELEASED;
 
-       if (j == 1)
-         x += 2 * ED_GADGET_DISTANCE;
-       y += ED_GADGET_DISTANCE;
+       if (j == 0)
+       {
+         x = DX + editor.button.prev_level.x;
+         y = DY + editor.button.prev_level.y;
+       }
+       else
+       {
+         x = DX + editor.button.next_level.x;
+         y = DY + editor.button.next_level.y;
+       }
 
        gd_x1 = gd->src_x;
        gd_y1 = gd->src_y;
@@ -5527,20 +5611,28 @@ static void CreateCounterButtons()
        int font_type = FONT_INPUT_1;
        int font_type_active = FONT_INPUT_1_ACTIVE;
        int gd_width = ED_WIN_COUNT_XSIZE;
+       int border_size = ED_BORDER_SIZE;
 
        id = counterbutton_info[i].gadget_id_text;
        event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
 
        if (i == ED_COUNTER_ID_SELECT_LEVEL)
        {
+         int graphic = IMG_EDITOR_INPUT_GFX_LEVEL_NUMBER;
+         struct GraphicInfo *gd = &graphic_info[graphic];
+
+         gd_bitmap = gd->bitmap;
+
+         x = DX + editor.input.level_number.x;
+         y = DY + editor.input.level_number.y;
+
+         gd_x = gd->src_x;
+         gd_y = gd->src_y;
+         gd_width = gd->width;
+         border_size = gd->border_size;
+
          font_type = FONT_LEVEL_NUMBER;
          font_type_active = FONT_LEVEL_NUMBER_ACTIVE;
-         x += 2 * ED_GADGET_DISTANCE;
-         y -= ED_GADGET_DISTANCE;
-
-         gd_x = DOOR_GFX_PAGEX6 + ED_WIN_COUNT2_XPOS;
-         gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT2_YPOS;
-         gd_width = ED_WIN_COUNT2_XSIZE;
        }
        else
        {
@@ -5562,7 +5654,7 @@ static void CreateCounterButtons()
                          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, ED_BORDER_SIZE,
+                         GDI_BORDER_SIZE, border_size, border_size,
                          GDI_DESIGN_WIDTH, gd_width,
                          GDI_EVENT_MASK, event_mask,
                          GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
@@ -6318,6 +6410,9 @@ static void MapControlButtons()
   for (i = 0; i < ED_NUM_CTRL1_2_BUTTONS; i++)
     MapGadget(level_editor_gadget[i]);
 
+  /* map toolbox buttons (element properties button) */
+  MapGadget(level_editor_gadget[ED_NUM_CTRL1_4_BUTTONS]);
+
   /* map buttons to select elements */
   for (i = 0; i < ED_NUM_ELEMENTLIST_BUTTONS; i++)
     MapGadget(level_editor_gadget[GADGET_ID_ELEMENTLIST_FIRST + i]);
@@ -6575,26 +6670,27 @@ static void UnmapLevelEditorToolboxCustomGadgets()
 
 static void MapOrUnmapLevelEditorToolboxDrawingGadgets(boolean map)
 {
-  Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
   int i;
 
   for (i = 0; i < ED_NUM_CTRL1_BUTTONS; i++)
   {
     if (i != GADGET_ID_SINGLE_ITEMS &&
-       i != GADGET_ID_PROPERTIES &&
        i != GADGET_ID_PICK_ELEMENT)
     {
       struct GadgetInfo *gi = level_editor_gadget[i];
 
       if (map)
+      {
        MapGadget(gi);
+      }
       else
       {
+       int graphic = IMG_EDITOR_NO_TOOLBOX_BUTTON;
+       struct GraphicInfo *gd = &graphic_info[graphic];
+
        UnmapGadget(gi);
 
-       BlitBitmap(gd_bitmap, drawto,
-                  DOOR_GFX_PAGEX6 + ED_CTRL_NO_BUTTONS_GFX_XPOS,
-                  DOOR_GFX_PAGEY1 + ED_CTRL_NO_BUTTONS_GFX_YPOS,
+       BlitBitmap(gd->bitmap, drawto, gd->src_x, gd->src_y,
                   gi->width, gi->height, gi->x, gi->y);
 
        redraw_mask |= REDRAW_DOOR_3;
@@ -7368,11 +7464,6 @@ static boolean playfield_area_changed = FALSE;
 
 void DrawLevelEd()
 {
-  int old_sx = SX;
-  int old_sy = SY;
-  int old_sxsize = SXSIZE;
-  int old_sysize = SYSIZE;
-
   StopAnimation();
 
   CloseDoor(DOOR_CLOSE_ALL);
@@ -7385,13 +7476,7 @@ void DrawLevelEd()
   /* needed if different viewport properties defined for editor */
   ChangeViewportPropertiesIfNeeded();
 
-  if (old_sx != SX ||
-      old_sy != SY ||
-      old_sxsize != SXSIZE ||
-      old_sysize != SYSIZE)
-    playfield_area_changed = TRUE;
-  else
-    playfield_area_changed = FALSE;
+  playfield_area_changed = DrawingAreaChanged();
 
   OpenDoor(DOOR_OPEN_1 | DOOR_OPEN_2 | DOOR_NO_DELAY);
 
@@ -7418,6 +7503,9 @@ void DrawLevelEd()
     level_ypos = -1;
   }
 
+  /* needed for gadgets drawn on background (like palette scrollbar) */
+  SetDoorBackgroundImage(IMG_UNDEFINED);
+
   /* copy default editor door content to main double buffer */
   BlitBitmap(graphic_info[IMG_BACKGROUND_PALETTE].bitmap, drawto,
             graphic_info[IMG_BACKGROUND_PALETTE].src_x,
@@ -7431,7 +7519,7 @@ void DrawLevelEd()
   BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
             DOOR_GFX_PAGEX8, 236, EXSIZE, EYSIZE, EX, EY);
 
-  redraw_mask |= REDRAW_ALL;
+  // redraw_mask |= REDRAW_ALL;
 
   FreeLevelEditorGadgets();
   CreateLevelEditorGadgets();
@@ -7487,8 +7575,6 @@ static void AdjustDrawingAreaGadgets()
   ed_fieldy = (ed_ysize < MAX_ED_FIELDY ? ed_ysize : max_ed_fieldy);
 
   ModifyGadget(level_editor_gadget[GADGET_ID_DRAWING_LEVEL],
-              GDI_WIDTH, ed_fieldx * MINI_TILEX,
-              GDI_HEIGHT, ed_fieldy * MINI_TILEY,
               GDI_AREA_SIZE, ed_fieldx, ed_fieldy,
               GDI_END);
 
@@ -7652,39 +7738,41 @@ static void ModifyEditorElementList()
 
     UnmapGadget(gi);
 
-    getMiniGraphicSource(el2edimg(element), &gd->bitmap, &gd->x, &gd->y);
+    getElementListGraphicSource(element, &gd->bitmap, &gd->x, &gd->y);
+
     ModifyGadget(gi, GDI_INFO_TEXT, getElementInfoText(element), GDI_END);
 
     MapGadget(gi);
   }
 }
 
+static void DrawDrawingElement(int element, struct EditorPaletteElementInfo *e)
+{
+  int graphic = el2edimg(element);
+  int tile_size = (e->tile_size >= TILESIZE ? TILESIZE : MINI_TILESIZE);
+
+  DrawSizedGraphicExt(drawto, DX + e->x, DY + e->y, graphic, 0, tile_size);
+}
+
 static void PickDrawingElement(int button, int element)
 {
+  struct
+  {
+    int *new_element;
+    struct EditorPaletteElementInfo *e;
+  } de, drawing_elements[] =
+  {
+    { &new_element1,   &editor.palette.element_left    },
+    { &new_element2,   &editor.palette.element_middle  },
+    { &new_element3,   &editor.palette.element_right   },
+  };
+
   if (button < 1 || button > 3)
     return;
 
-  if (button == 1)
-  {
-    new_element1 = element;
-    DrawMiniGraphicExt(drawto,
-                      DX + ED_WIN_MB_LEFT_XPOS, DY + ED_WIN_MB_LEFT_YPOS,
-                      el2edimg(new_element1));
-  }
-  else if (button == 2)
-  {
-    new_element2 = element;
-    DrawMiniGraphicExt(drawto,
-                      DX + ED_WIN_MB_MIDDLE_XPOS, DY + ED_WIN_MB_MIDDLE_YPOS,
-                      el2edimg(new_element2));
-  }
-  else
-  {
-    new_element3 = element;
-    DrawMiniGraphicExt(drawto,
-                      DX + ED_WIN_MB_RIGHT_XPOS, DY + ED_WIN_MB_RIGHT_YPOS,
-                      el2edimg(new_element3));
-  }
+  de = drawing_elements[button - 1];
+
+  DrawDrawingElement((*de.new_element = element), de.e);
 
   redraw_mask |= REDRAW_DOOR_1;
 }
@@ -10074,7 +10162,10 @@ static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
        else if (element >= NUM_FILE_ELEMENTS)
          element_mapped = EL_UNKNOWN;
 
-       printf("%c%03d", (mode == CB_DUMP_BRUSH ? '`' : '¸'), element_mapped);
+       // dump brush as level sketch text for the R'n'D forum:
+       // - large tiles: `xxx (0x60 ASCII)
+       // - small tiles: ¸xxx (0xb8 ISO-8859-1, 0xc2b8 UTF-8)
+       printf("%s%03d", (mode == CB_DUMP_BRUSH ? "`" : "¸"), element_mapped);
       }
 
       printf("\n");
@@ -10233,11 +10324,11 @@ static int DrawLevelText(int sx, int sy, char letter, int mode)
   /* map lower case letters to upper case and convert special characters */
   if (letter >= 'a' && letter <= 'z')
     letter_element = EL_CHAR_ASCII0 + letter + (int)('A' - 'a');
-  else if (letter == 'ä' || letter == 'Ä')
+  else if (letter == CHAR_BYTE_UMLAUT_a || letter == CHAR_BYTE_UMLAUT_A)
     letter_element = EL_CHAR_AUMLAUT;
-  else if (letter == 'ö' || letter == 'Ö')
+  else if (letter == CHAR_BYTE_UMLAUT_o || letter == CHAR_BYTE_UMLAUT_O)
     letter_element = EL_CHAR_OUMLAUT;
-  else if (letter == 'ü' || letter == 'Ü')
+  else if (letter == CHAR_BYTE_UMLAUT_u || letter == CHAR_BYTE_UMLAUT_U)
     letter_element = EL_CHAR_UUMLAUT;
   else if (letter == '^')
     letter_element = EL_CHAR_COPYRIGHT;
@@ -10282,6 +10373,10 @@ static int DrawLevelText(int sx, int sy, char letter, int mode)
     case TEXT_WRITECHAR:
       if (letter_element >= EL_CHAR_START && letter_element <= EL_CHAR_END)
       {
+       if (new_element1 >= EL_STEEL_CHAR_START &&
+           new_element1 <= EL_STEEL_CHAR_END)
+         letter_element = letter_element - EL_CHAR_START + EL_STEEL_CHAR_START;
+
        delete_buffer[sx - start_sx] = Feld[lx][ly];
        Feld[lx][ly] = letter_element;
 
@@ -11058,7 +11153,6 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 
   if (id < ED_NUM_CTRL1_BUTTONS &&
       id != GADGET_ID_SINGLE_ITEMS &&
-      id != GADGET_ID_PROPERTIES &&
       id != GADGET_ID_PICK_ELEMENT &&
       edit_mode != ED_MODE_DRAWING &&
       drawing_function != GADGET_ID_PICK_ELEMENT &&
@@ -11184,6 +11278,27 @@ static void HandleControlButtons(struct GadgetInfo *gi)
 
       break;
 
+    case GADGET_ID_PROPERTIES:
+      if (edit_mode != ED_MODE_PROPERTIES)
+      {
+       properties_element = new_element;
+       DrawPropertiesWindow();
+       edit_mode = ED_MODE_PROPERTIES;
+
+       last_level_drawing_function = drawing_function;
+       ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS],
+                     MB_LEFTBUTTON);
+      }
+      else
+      {
+       DrawDrawingWindow();
+       edit_mode = ED_MODE_DRAWING;
+
+       ClickOnGadget(level_editor_gadget[last_level_drawing_function],
+                     MB_LEFTBUTTON);
+      }
+      break;
+
     case GADGET_ID_WRAP_LEFT:
       WrapLevel(-step, 0);
       break;
@@ -11220,25 +11335,8 @@ static void HandleControlButtons(struct GadgetInfo *gi)
       RandomPlacement(new_element);
       break;
 
-    case GADGET_ID_PROPERTIES:
-      if (edit_mode != ED_MODE_PROPERTIES)
-      {
-       properties_element = new_element;
-       DrawPropertiesWindow();
-       edit_mode = ED_MODE_PROPERTIES;
-
-       last_level_drawing_function = drawing_function;
-       ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS],
-                     MB_LEFTBUTTON);
-      }
-      else
-      {
-       DrawDrawingWindow();
-       edit_mode = ED_MODE_DRAWING;
-
-       ClickOnGadget(level_editor_gadget[last_level_drawing_function],
-                     MB_LEFTBUTTON);
-      }
+    case GADGET_ID_ZOOM:
+      printf("::: zoom button pressed with mouse button %d\n", button);
       break;
 
     case GADGET_ID_CUSTOM_COPY_FROM:
@@ -11382,7 +11480,7 @@ static void HandleControlButtons(struct GadgetInfo *gi)
       /* needed before playing if editor playfield area has different size */
       ClearRectangle(drawto, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE);
 
-      redraw_mask = REDRAW_ALL;
+      // redraw_mask = REDRAW_ALL;
 
       level_editor_test_game = TRUE;
 
@@ -11594,6 +11692,10 @@ void HandleLevelEditorKeyInput(Key key)
 
     if (id != GADGET_ID_NONE)
       ClickOnGadget(level_editor_gadget[id], button);
+    else if (letter >= '1' && letter <= '3')
+      ClickOnGadget(level_editor_gadget[GADGET_ID_PROPERTIES], letter - '0');
+    else if (letter == '?')
+      ClickOnGadget(level_editor_gadget[GADGET_ID_PROPERTIES], button);
     else if (letter == '.')
       ClickOnGadget(level_editor_gadget[GADGET_ID_SINGLE_ITEMS], button);
     else if (key == KSYM_Return ||
@@ -11602,7 +11704,7 @@ void HandleLevelEditorKeyInput(Key key)
       ClickOnGadget(level_editor_gadget[GADGET_ID_TEST], button);
     else
       for (i = 0; i < ED_NUM_CTRL_BUTTONS; i++)
-       if (letter && letter == control_info[i].shortcut)
+       if (letter && letter == controlbutton_info[i].shortcut)
          if (!anyTextGadgetActive())
            ClickOnGadget(level_editor_gadget[i], button);
   }
@@ -11657,7 +11759,7 @@ void PrintEditorGadgetInfoText(struct GadgetInfo *gi)
 
   if (gi->custom_id < ED_NUM_CTRL_BUTTONS)
   {
-    int key = control_info[gi->custom_id].shortcut;
+    int key = controlbutton_info[gi->custom_id].shortcut;
 
     if (key)
     {