+static int num_editor_el_supaplex = SIZEOF_ARRAY_INT(editor_el_supaplex);
+
+static int editor_el_diamond_caves[] =
+{
+ EL_CHAR('D'),
+ EL_CHAR('I'),
+ EL_CHAR('A'),
+ EL_CHAR('-'),
+
+ EL_CHAR('M'),
+ EL_CHAR('O'),
+ EL_CHAR('N'),
+ EL_CHAR('D'),
+
+ EL_CHAR('C'),
+ EL_CHAR('A'),
+ EL_CHAR('V'),
+ EL_CHAR('E'),
+
+ EL_CHAR('S'),
+ EL_CHAR(' '),
+ EL_CHAR('I'),
+ EL_CHAR('I'),
+
+ EL_PEARL,
+ EL_CRYSTAL,
+ EL_WALL_PEARL,
+ EL_WALL_CRYSTAL,
+
+ EL_CONVEYOR_BELT_1_LEFT,
+ EL_CONVEYOR_BELT_1_MIDDLE,
+ EL_CONVEYOR_BELT_1_RIGHT,
+ EL_CONVEYOR_BELT_1_SWITCH_MIDDLE,
+
+ EL_CONVEYOR_BELT_2_LEFT,
+ EL_CONVEYOR_BELT_2_MIDDLE,
+ EL_CONVEYOR_BELT_2_RIGHT,
+ EL_CONVEYOR_BELT_2_SWITCH_MIDDLE,
+
+ EL_CONVEYOR_BELT_3_LEFT,
+ EL_CONVEYOR_BELT_3_MIDDLE,
+ EL_CONVEYOR_BELT_3_RIGHT,
+ EL_CONVEYOR_BELT_3_SWITCH_MIDDLE,
+
+ EL_CONVEYOR_BELT_4_LEFT,
+ EL_CONVEYOR_BELT_4_MIDDLE,
+ EL_CONVEYOR_BELT_4_RIGHT,
+ EL_CONVEYOR_BELT_4_SWITCH_MIDDLE,
+
+ EL_CONVEYOR_BELT_1_SWITCH_LEFT,
+ EL_CONVEYOR_BELT_2_SWITCH_LEFT,
+ EL_CONVEYOR_BELT_3_SWITCH_LEFT,
+ EL_CONVEYOR_BELT_4_SWITCH_LEFT,
+
+ EL_CONVEYOR_BELT_1_SWITCH_RIGHT,
+ EL_CONVEYOR_BELT_2_SWITCH_RIGHT,
+ EL_CONVEYOR_BELT_3_SWITCH_RIGHT,
+ EL_CONVEYOR_BELT_4_SWITCH_RIGHT,
+
+ EL_SWITCHGATE_OPEN,
+ EL_SWITCHGATE_CLOSED,
+ EL_SWITCHGATE_SWITCH_UP,
+ EL_ENVELOPE,
+
+ EL_TIMEGATE_CLOSED,
+ EL_TIMEGATE_OPEN,
+ EL_TIMEGATE_SWITCH,
+ EL_EMPTY,
+
+ EL_LANDMINE,
+ EL_INVISIBLE_SAND,
+ EL_STEELWALL_SLANTED,
+ EL_EMPTY,
+
+ EL_SIGN_EXCLAMATION,
+ EL_SIGN_STOP,
+ EL_LIGHT_SWITCH,
+ EL_LIGHT_SWITCH_ACTIVE,
+
+ EL_SHIELD_NORMAL,
+ EL_SHIELD_DEADLY,
+ EL_EXTRA_TIME,
+ EL_EMPTY,
+};
+static int num_editor_el_diamond_caves = SIZEOF_ARRAY_INT(editor_el_diamond_caves);
+
+static int editor_el_dx_boulderdash[] =
+{
+ EL_CHAR('D'),
+ EL_CHAR('X'),
+ EL_CHAR('-'),
+ EL_CHAR(' '),
+
+ EL_CHAR('B'),
+ EL_CHAR('O'),
+ EL_CHAR('U'),
+ EL_CHAR('L'),
+
+ EL_CHAR('-'),
+ EL_CHAR('D'),
+ EL_CHAR('E'),
+ EL_CHAR('R'),
+
+ EL_CHAR('D'),
+ EL_CHAR('A'),
+ EL_CHAR('S'),
+ EL_CHAR('H'),
+
+ EL_SPRING,
+ EL_TUBE_RIGHT_DOWN,
+ EL_TUBE_HORIZONTAL_DOWN,
+ EL_TUBE_LEFT_DOWN,
+
+ EL_TUBE_HORIZONTAL,
+ EL_TUBE_VERTICAL_RIGHT,
+ EL_TUBE_ANY,
+ EL_TUBE_VERTICAL_LEFT,
+
+ EL_TUBE_VERTICAL,
+ EL_TUBE_RIGHT_UP,
+ EL_TUBE_HORIZONTAL_UP,
+ EL_TUBE_LEFT_UP,
+
+ EL_TRAP,
+ EL_DX_SUPABOMB,
+ EL_EMPTY,
+ EL_EMPTY
+};
+static int num_editor_el_dx_boulderdash = SIZEOF_ARRAY_INT(editor_el_dx_boulderdash);
+
+static int editor_el_chars[] =
+{
+ EL_CHAR('T'),
+ EL_CHAR('E'),
+ EL_CHAR('X'),
+ EL_CHAR('T'),
+
+ 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('0'),
+ EL_CHAR('1'),
+ EL_CHAR('2'),
+ EL_CHAR('3'),
+
+ EL_CHAR('4'),
+ EL_CHAR('5'),
+ EL_CHAR('6'),
+ EL_CHAR('7'),
+
+ EL_CHAR('8'),
+ EL_CHAR('9'),
+ EL_CHAR(':'),
+ EL_CHAR(';'),
+
+ EL_CHAR('<'),
+ EL_CHAR('='),
+ EL_CHAR('>'),
+ EL_CHAR('?'),
+
+ EL_CHAR('@'),
+ EL_CHAR('A'),
+ EL_CHAR('B'),
+ EL_CHAR('C'),
+
+ EL_CHAR('D'),
+ EL_CHAR('E'),
+ EL_CHAR('F'),
+ EL_CHAR('G'),
+
+ EL_CHAR('H'),
+ EL_CHAR('I'),
+ EL_CHAR('J'),
+ EL_CHAR('K'),
+
+ EL_CHAR('L'),
+ EL_CHAR('M'),
+ EL_CHAR('N'),
+ EL_CHAR('O'),
+
+ EL_CHAR('P'),
+ EL_CHAR('Q'),
+ EL_CHAR('R'),
+ EL_CHAR('S'),
+
+ EL_CHAR('T'),
+ EL_CHAR('U'),
+ EL_CHAR('V'),
+ EL_CHAR('W'),
+
+ 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('|')
+};
+static int num_editor_el_chars = SIZEOF_ARRAY_INT(editor_el_chars);
+
+static int editor_el_custom[] =
+{
+ EL_CHAR('C'),
+ EL_CHAR('U'),
+ EL_CHAR('S'),
+ EL_CHAR('-'),
+
+ EL_CHAR('T'),
+ EL_CHAR('O'),
+ EL_CHAR('M'),
+ EL_CHAR(' '),
+
+ EL_CHAR('E'),
+ EL_CHAR('L'),
+ EL_CHAR('E'),
+ EL_CHAR('M'),
+
+ EL_CHAR('E'),
+ EL_CHAR('N'),
+ EL_CHAR('T'),
+ EL_CHAR('S'),
+
+ EL_CUSTOM_START + 0,
+ EL_CUSTOM_START + 1,
+ EL_CUSTOM_START + 2,
+ EL_CUSTOM_START + 3,
+
+ EL_CUSTOM_START + 4,
+ EL_CUSTOM_START + 5,
+ EL_CUSTOM_START + 6,
+ EL_CUSTOM_START + 7,
+
+ EL_CUSTOM_START + 8,
+ EL_CUSTOM_START + 9,
+ EL_CUSTOM_START + 10,
+ EL_CUSTOM_START + 11,
+
+ EL_CUSTOM_START + 12,
+ EL_CUSTOM_START + 13,
+ EL_CUSTOM_START + 14,
+ EL_CUSTOM_START + 15,
+
+ EL_CUSTOM_START + 16,
+ EL_CUSTOM_START + 17,
+ EL_CUSTOM_START + 18,
+ EL_CUSTOM_START + 19,
+
+ EL_CUSTOM_START + 20,
+ EL_CUSTOM_START + 21,
+ EL_CUSTOM_START + 22,
+ EL_CUSTOM_START + 23,
+
+ EL_CUSTOM_START + 24,
+ EL_CUSTOM_START + 25,
+ EL_CUSTOM_START + 26,
+ EL_CUSTOM_START + 27,
+
+ EL_CUSTOM_START + 28,
+ EL_CUSTOM_START + 29,
+ EL_CUSTOM_START + 30,
+ EL_CUSTOM_START + 31,
+
+ EL_CUSTOM_START + 32,
+ EL_CUSTOM_START + 33,
+ EL_CUSTOM_START + 34,
+ EL_CUSTOM_START + 35,
+
+ EL_CUSTOM_START + 36,
+ EL_CUSTOM_START + 37,
+ EL_CUSTOM_START + 38,
+ EL_CUSTOM_START + 39,
+
+ EL_CUSTOM_START + 40,
+ EL_CUSTOM_START + 41,
+ EL_CUSTOM_START + 42,
+ EL_CUSTOM_START + 43,
+
+ EL_CUSTOM_START + 44,
+ EL_CUSTOM_START + 45,
+ EL_CUSTOM_START + 46,
+ EL_CUSTOM_START + 47,
+
+ EL_CUSTOM_START + 48,
+ EL_CUSTOM_START + 49,
+ EL_CUSTOM_START + 50,
+ EL_CUSTOM_START + 51,
+
+ EL_CUSTOM_START + 52,
+ EL_CUSTOM_START + 53,
+ EL_CUSTOM_START + 54,
+ EL_CUSTOM_START + 55,
+
+ EL_CUSTOM_START + 56,
+ EL_CUSTOM_START + 57,
+ EL_CUSTOM_START + 58,
+ EL_CUSTOM_START + 59,
+
+ EL_CUSTOM_START + 60,
+ EL_CUSTOM_START + 61,
+ EL_CUSTOM_START + 62,
+ EL_CUSTOM_START + 63,
+
+ EL_CUSTOM_START + 64,
+ EL_CUSTOM_START + 65,
+ EL_CUSTOM_START + 66,
+ EL_CUSTOM_START + 67,
+
+ EL_CUSTOM_START + 68,
+ EL_CUSTOM_START + 69,
+ EL_CUSTOM_START + 70,
+ EL_CUSTOM_START + 71,
+
+ EL_CUSTOM_START + 72,
+ EL_CUSTOM_START + 73,
+ EL_CUSTOM_START + 74,
+ EL_CUSTOM_START + 75,
+
+ EL_CUSTOM_START + 76,
+ EL_CUSTOM_START + 77,
+ EL_CUSTOM_START + 78,
+ EL_CUSTOM_START + 79,
+
+ EL_CUSTOM_START + 80,
+ EL_CUSTOM_START + 81,
+ EL_CUSTOM_START + 82,
+ EL_CUSTOM_START + 83,
+
+ EL_CUSTOM_START + 84,
+ EL_CUSTOM_START + 85,
+ EL_CUSTOM_START + 86,
+ EL_CUSTOM_START + 87,
+
+ EL_CUSTOM_START + 88,
+ EL_CUSTOM_START + 89,
+ EL_CUSTOM_START + 90,
+ EL_CUSTOM_START + 91,
+
+ EL_CUSTOM_START + 92,
+ EL_CUSTOM_START + 93,
+ EL_CUSTOM_START + 94,
+ EL_CUSTOM_START + 95,
+
+ EL_CUSTOM_START + 96,
+ EL_CUSTOM_START + 97,
+ EL_CUSTOM_START + 98,
+ EL_CUSTOM_START + 99,
+
+ EL_CUSTOM_START + 100,
+ EL_CUSTOM_START + 101,
+ EL_CUSTOM_START + 102,
+ EL_CUSTOM_START + 103,
+
+ EL_CUSTOM_START + 104,
+ EL_CUSTOM_START + 105,
+ EL_CUSTOM_START + 106,
+ EL_CUSTOM_START + 107,
+
+ EL_CUSTOM_START + 108,
+ EL_CUSTOM_START + 109,
+ EL_CUSTOM_START + 110,
+ EL_CUSTOM_START + 111,
+
+ EL_CUSTOM_START + 112,
+ EL_CUSTOM_START + 113,
+ EL_CUSTOM_START + 114,
+ EL_CUSTOM_START + 115,
+
+ EL_CUSTOM_START + 116,
+ EL_CUSTOM_START + 117,
+ EL_CUSTOM_START + 118,
+ EL_CUSTOM_START + 119,
+
+ EL_CUSTOM_START + 120,
+ EL_CUSTOM_START + 121,
+ EL_CUSTOM_START + 122,
+ EL_CUSTOM_START + 123,
+
+ EL_CUSTOM_START + 124,
+ EL_CUSTOM_START + 125,
+ EL_CUSTOM_START + 126,
+ EL_CUSTOM_START + 127
+};
+static int num_editor_el_custom = SIZEOF_ARRAY_INT(editor_el_custom);
+
+static int *editor_elements = NULL; /* dynamically allocated */
+static int num_editor_elements = 0; /* dynamically determined */
+
+static struct
+{
+ boolean *setup_value;
+ int *element_list;
+ int *element_list_size;
+
+ boolean last_setup_value;
+}
+editor_elements_info[] =
+{
+ { &setup.editor.el_boulderdash, editor_el_boulderdash,
+ &num_editor_el_boulderdash },
+ { &setup.editor.el_emerald_mine, editor_el_emerald_mine,
+ &num_editor_el_emerald_mine },
+ { &setup.editor.el_more, editor_el_more,
+ &num_editor_el_more },
+ { &setup.editor.el_sokoban, editor_el_sokoban,
+ &num_editor_el_sokoban },
+ { &setup.editor.el_supaplex, editor_el_supaplex,
+ &num_editor_el_supaplex },
+ { &setup.editor.el_diamond_caves, editor_el_diamond_caves,
+ &num_editor_el_diamond_caves },
+ { &setup.editor.el_dx_boulderdash, editor_el_dx_boulderdash,
+ &num_editor_el_dx_boulderdash },
+ { &setup.editor.el_chars, editor_el_chars,
+ &num_editor_el_chars },
+ { &setup.editor.el_custom, editor_el_custom,
+ &num_editor_el_custom },
+ { NULL, NULL,
+ NULL }
+};
+
+static void ReinitializeElementList()
+{
+ int pos = 0;
+ int i, j;
+
+ if (editor_elements != NULL)
+ free(editor_elements);
+
+ num_editor_elements = 0;
+
+ /* determine size of element list */
+ for (i=0; editor_elements_info[i].setup_value != NULL; i++)
+ if (*editor_elements_info[i].setup_value)
+ num_editor_elements += *editor_elements_info[i].element_list_size;
+
+ if (num_editor_elements < ED_NUM_ELEMENTLIST_BUTTONS)
+ {
+ /* workaround: offer at least as many elements as element buttons exist */
+ int list_nr = 1; /* see above: editor_elements_info for Emerald Mine */
+
+ *editor_elements_info[list_nr].setup_value = TRUE;
+ num_editor_elements += *editor_elements_info[list_nr].element_list_size;
+ }
+
+ editor_elements = checked_malloc(num_editor_elements * sizeof(int));
+
+ /* fill element list */
+ for (i=0; editor_elements_info[i].setup_value != NULL; i++)
+ if (*editor_elements_info[i].setup_value)
+ for (j=0; j<*editor_elements_info[i].element_list_size; j++)
+ editor_elements[pos++] = editor_elements_info[i].element_list[j];
+}
+
+static void ReinitializeElementListButtons()
+{
+ static boolean initialization_needed = TRUE;
+ int i;
+
+ if (!initialization_needed) /* check if editor element setup has changed */
+ for (i=0; editor_elements_info[i].setup_value != NULL; i++)
+ if (editor_elements_info[i].last_setup_value !=
+ *editor_elements_info[i].setup_value)
+ initialization_needed = TRUE;
+
+ if (!initialization_needed)
+ return;
+
+ FreeLevelEditorGadgets();
+ CreateLevelEditorGadgets();
+
+ /* store current setup values for next invocation of this function */
+ for (i=0; editor_elements_info[i].setup_value != NULL; i++)
+ editor_elements_info[i].last_setup_value =
+ *editor_elements_info[i].setup_value;
+
+ initialization_needed = FALSE;
+}
+
+static int getCounterGadgetWidth()
+{
+ return (DXSIZE + getFontWidth(FONT_INPUT) - 2 * ED_GADGET_DISTANCE);
+}
+
+static int getMaxInfoTextLength()
+{
+ return (SXSIZE / getFontWidth(FONT_TEXT_2));
+}
+
+static char *getElementInfoText(int element)
+{
+ char *info_text = NULL;
+
+ if (element < NUM_FILE_ELEMENTS)
+ {
+ if (element_info[element].custom_description != NULL)
+ info_text = element_info[element].custom_description;
+ else if (element_info[element].editor_description != NULL)
+ info_text = element_info[element].editor_description;
+ }
+
+ if (info_text == NULL)
+ {
+ info_text = "unknown";
+
+ Error(ERR_WARN, "no element description for element %d", element);
+ }
+
+ return info_text;
+}
+
+static void ScrollMiniLevel(int from_x, int from_y, int scroll)
+{
+ int x,y;
+ int dx = (scroll == ED_SCROLL_LEFT ? -1 : scroll == ED_SCROLL_RIGHT ? 1 : 0);
+ int dy = (scroll == ED_SCROLL_UP ? -1 : scroll == ED_SCROLL_DOWN ? 1 : 0);
+
+ BlitBitmap(drawto, drawto,
+ SX + (dx == -1 ? MINI_TILEX : 0),
+ SY + (dy == -1 ? MINI_TILEY : 0),
+ (ed_fieldx * MINI_TILEX) - (dx != 0 ? MINI_TILEX : 0),
+ (ed_fieldy * MINI_TILEY) - (dy != 0 ? MINI_TILEY : 0),
+ SX + (dx == +1 ? MINI_TILEX : 0),
+ SY + (dy == +1 ? MINI_TILEY : 0));
+ if (dx)
+ {
+ x = (dx == 1 ? 0 : ed_fieldx - 1);
+ for(y=0; y<ed_fieldy; y++)
+ DrawMiniElementOrWall(x, y, from_x, from_y);
+ }
+ else if (dy)
+ {
+ y = (dy == 1 ? 0 : ed_fieldy - 1);
+ for(x=0; x<ed_fieldx; x++)
+ DrawMiniElementOrWall(x, y, from_x, from_y);
+ }
+
+ redraw_mask |= REDRAW_FIELD;
+ BackToFront();
+}
+
+static void CreateControlButtons()
+{
+ Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
+ struct GadgetInfo *gi;
+ unsigned long 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)
+ {
+ button_type = GD_TYPE_RADIO_BUTTON;
+ radio_button_nr = RADIO_NR_DRAWING_TOOLBOX;
+ checked = (id == drawing_function ? TRUE : FALSE);
+ event_mask = GD_EVENT_PRESSED;
+ }
+ 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 ||
+ id == GADGET_ID_WRAP_DOWN)
+ event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
+ else
+ event_mask = GD_EVENT_RELEASED;
+ }
+
+ if (id < ED_NUM_CTRL1_BUTTONS)
+ {
+ 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;
+ }
+ else
+ {
+ 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_CTRL_BUTTONS_GFX_YPOS + gd_yoffset;
+ gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
+
+ 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_WIDTH, width,
+ GDI_HEIGHT, height,
+ GDI_TYPE, button_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_EVENT_MASK, event_mask,
+ GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
+ GDI_CALLBACK_ACTION, HandleControlButtons,
+ GDI_END);
+
+ if (gi == NULL)
+ Error(ERR_EXIT, "cannot create gadget");
+
+ level_editor_gadget[id] = gi;
+ }
+
+ /* create buttons for scrolling of drawing area and element list */
+ for (i=0; i<ED_NUM_SCROLLBUTTONS; i++)
+ {
+ int id = scrollbutton_info[i].gadget_id;
+ int x, y, width, height;
+ int gd_x1, gd_x2, gd_y1, gd_y2;
+
+ x = scrollbutton_info[i].x;
+ y = scrollbutton_info[i].y;
+
+ 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 = ED_SCROLLBUTTON2_XSIZE;
+ height = ED_SCROLLBUTTON2_YSIZE;
+ gd_x1 = DOOR_GFX_PAGEX8 + scrollbutton_info[i].xpos;
+ gd_y1 = DOOR_GFX_PAGEY1 + scrollbutton_info[i].ypos;
+ gd_x2 = gd_x1 - ED_SCROLLBUTTON2_XSIZE;
+ gd_y2 = gd_y1;
+ }
+ else
+ {
+ x += SX;
+ y += SY;
+ width = ED_SCROLLBUTTON_XSIZE;
+ height = ED_SCROLLBUTTON_YSIZE;
+ gd_x1 = DOOR_GFX_PAGEX8 + scrollbutton_info[i].xpos;
+ gd_y1 = DOOR_GFX_PAGEY1 + scrollbutton_info[i].ypos;
+ gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
+ gd_y2 = gd_y1;
+ }
+
+ gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_CUSTOM_TYPE_ID, i,
+ GDI_INFO_TEXT, scrollbutton_info[i].infotext,
+ GDI_X, x,
+ GDI_Y, y,
+ GDI_WIDTH, width,
+ GDI_HEIGHT, height,
+ GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
+ GDI_STATE, GD_BUTTON_UNPRESSED,
+ GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y1,
+ GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y2,
+ GDI_EVENT_MASK, event_mask,
+ GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
+ GDI_CALLBACK_ACTION, HandleControlButtons,
+ GDI_END);
+
+ if (gi == NULL)
+ Error(ERR_EXIT, "cannot create gadget");
+
+ level_editor_gadget[id] = gi;
+ }
+
+ /* create buttons for element list */
+ for (i=0; i<ED_NUM_ELEMENTLIST_BUTTONS; i++)
+ {
+ Bitmap *deco_bitmap;
+ int deco_x, deco_y, deco_xpos, deco_ypos;
+ int gd_xoffset, gd_yoffset;
+ int gd_x1, gd_x2, gd_y;
+ int x = i % ED_ELEMENTLIST_BUTTONS_HORIZ;
+ int y = i / ED_ELEMENTLIST_BUTTONS_HORIZ;
+ int id = GADGET_ID_ELEMENTLIST_FIRST + i;
+ int element = editor_elements[i];
+
+ event_mask = GD_EVENT_RELEASED;
+
+ gd_xoffset = ED_ELEMENTLIST_XPOS + x * ED_ELEMENTLIST_XSIZE;
+ gd_yoffset = ED_ELEMENTLIST_YPOS + y * ED_ELEMENTLIST_YSIZE;
+
+ gd_x1 = DOOR_GFX_PAGEX6 + ED_ELEMENTLIST_XPOS + ED_ELEMENTLIST_XSIZE;
+ gd_x2 = DOOR_GFX_PAGEX6 + ED_ELEMENTLIST_XPOS;
+ gd_y = DOOR_GFX_PAGEY1 + ED_ELEMENTLIST_YPOS;
+
+ getMiniGraphicSource(el2edimg(element), &deco_bitmap, &deco_x, &deco_y);
+ deco_xpos = (ED_ELEMENTLIST_XSIZE - MINI_TILEX) / 2;
+ deco_ypos = (ED_ELEMENTLIST_YSIZE - MINI_TILEY) / 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_WIDTH, ED_ELEMENTLIST_XSIZE,
+ GDI_HEIGHT, ED_ELEMENTLIST_YSIZE,
+ GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
+ GDI_STATE, GD_BUTTON_UNPRESSED,
+ GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
+ GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
+ 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_SHIFTING, 1, 1,
+ GDI_EVENT_MASK, event_mask,
+ GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
+ GDI_CALLBACK_ACTION, HandleControlButtons,
+ GDI_END);
+
+ if (gi == NULL)
+ Error(ERR_EXIT, "cannot create gadget");
+
+ level_editor_gadget[id] = gi;
+ }
+}
+
+static void CreateCounterButtons()
+{
+ int max_infotext_len = getMaxInfoTextLength();
+ int i;
+
+ for (i=0; i<ED_NUM_COUNTERBUTTONS; i++)
+ {
+ int j;
+ int xpos = SX + counterbutton_info[i].x; /* xpos of down count button */
+ int ypos = SY + counterbutton_info[i].y;
+
+ for (j=0; j<2; j++)
+ {
+ Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
+ struct GadgetInfo *gi;
+ int id = (j == 0 ?
+ counterbutton_info[i].gadget_id_down :
+ counterbutton_info[i].gadget_id_up);
+ int gd_xoffset;
+ int gd_x, gd_x1, gd_x2, gd_y;
+ int x_size, y_size;
+ unsigned long event_mask;
+ char infotext[max_infotext_len + 1];
+
+ event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
+
+ if (i == ED_COUNTER_ID_SELECT_LEVEL)
+ {
+ int sid = (j == 0 ?
+ ED_SCROLLBUTTON_ID_AREA_LEFT :
+ ED_SCROLLBUTTON_ID_AREA_RIGHT);
+
+ event_mask |= GD_EVENT_RELEASED;
+
+ if (j == 1)
+ xpos += 2 * ED_GADGET_DISTANCE;
+ ypos += ED_GADGET_DISTANCE;
+
+ gd_x1 = DOOR_GFX_PAGEX8 + scrollbutton_info[sid].xpos;
+ gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
+ gd_y = DOOR_GFX_PAGEY1 + scrollbutton_info[sid].ypos;
+ x_size = ED_SCROLLBUTTON_XSIZE;
+ y_size = ED_SCROLLBUTTON_YSIZE;
+ }
+ else
+ {
+ gd_xoffset = (j == 0 ? ED_BUTTON_MINUS_XPOS : ED_BUTTON_PLUS_XPOS);
+ gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
+ gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
+ gd_y = DOOR_GFX_PAGEY1 + ED_BUTTON_COUNT_YPOS;
+ x_size = ED_BUTTON_COUNT_XSIZE;
+ y_size = ED_BUTTON_COUNT_YSIZE;
+ }
+
+ sprintf(infotext, "%s counter value by 1, 5 or 10",
+ (j == 0 ? "decrease" : "increase"));
+
+ gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_CUSTOM_TYPE_ID, i,
+ GDI_INFO_TEXT, infotext,
+ GDI_X, xpos,
+ GDI_Y, ypos,
+ GDI_WIDTH, x_size,
+ GDI_HEIGHT, y_size,
+ GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
+ GDI_STATE, GD_BUTTON_UNPRESSED,
+ GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
+ GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
+ GDI_EVENT_MASK, event_mask,
+ GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
+ GDI_CALLBACK_ACTION, HandleCounterButtons,
+ GDI_END);
+
+ if (gi == NULL)
+ Error(ERR_EXIT, "cannot create gadget");
+
+ level_editor_gadget[id] = gi;
+ xpos += gi->width + ED_GADGET_DISTANCE; /* xpos of text count button */
+
+ if (j == 0)
+ {
+ int font_type = FONT_INPUT;
+ int gd_width = ED_WIN_COUNT_XSIZE;
+
+ id = counterbutton_info[i].gadget_id_text;
+ event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
+
+ if (i == ED_COUNTER_ID_SELECT_LEVEL)
+ {
+ font_type = FONT_LEVEL_NUMBER;
+
+ xpos += 2 * ED_GADGET_DISTANCE;
+ ypos -= 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
+ {
+ gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
+ gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
+ }
+
+ gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_CUSTOM_TYPE_ID, i,
+ GDI_INFO_TEXT, "enter counter value",
+ GDI_X, xpos,
+ GDI_Y, ypos,
+ GDI_TYPE, GD_TYPE_TEXTINPUT_NUMERIC,
+ GDI_NUMBER_VALUE, 0,
+ GDI_NUMBER_MIN, counterbutton_info[i].min_value,
+ GDI_NUMBER_MAX, counterbutton_info[i].max_value,
+ GDI_TEXT_SIZE, 3,
+ GDI_TEXT_FONT, font_type,
+ 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_EVENT_MASK, event_mask,
+ GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
+ GDI_CALLBACK_ACTION, HandleCounterButtons,
+ GDI_END);
+
+ if (gi == NULL)
+ Error(ERR_EXIT, "cannot create gadget");
+
+ level_editor_gadget[id] = gi;
+ xpos += gi->width + ED_GADGET_DISTANCE; /* xpos of up count button */
+ }
+ }
+ }
+}
+
+static void CreateDrawingAreas()
+{
+ struct GadgetInfo *gi;
+ unsigned long event_mask;
+ int id;
+ int i;
+
+ event_mask =
+ GD_EVENT_PRESSED | GD_EVENT_RELEASED | GD_EVENT_MOVING |
+ GD_EVENT_OFF_BORDERS;
+
+ /* one for the level drawing area ... */
+ id = GADGET_ID_DRAWING_LEVEL;
+ gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_X, SX,
+ GDI_Y, SY,
+ GDI_TYPE, GD_TYPE_DRAWING_AREA,
+ GDI_AREA_SIZE, ed_fieldx, ed_fieldy,
+ 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;
+
+ /* ... up to eight areas for element content ... */
+ for (i=0; i<MAX_ELEMENT_CONTENTS; i++)
+ {
+ int gx = SX + ED_AREA_ELEM_CONTENT_XPOS + 5 * (i % 4) * MINI_TILEX;
+ int gy = SX + ED_AREA_ELEM_CONTENT_YPOS + 6 * (i / 4) * MINI_TILEY;
+
+ id = GADGET_ID_ELEM_CONTENT_0 + i;
+ gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_CUSTOM_TYPE_ID, i,
+ GDI_X, gx,
+ GDI_Y, gy,
+ GDI_WIDTH, 3 * MINI_TILEX,
+ GDI_HEIGHT, 3 * 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;
+ }
+
+ /* ... one for the amoeba content */
+ id = GADGET_ID_AMOEBA_CONTENT;
+ gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_X, SX + ED_AREA_ELEM_CONTENT_XPOS,
+ GDI_Y, SY + ED_AREA_ELEM_CONTENT_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;
+ gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_X, SX + ED_AREA_RANDOM_BACKGROUND_XPOS,
+ GDI_Y, SY + ED_AREA_RANDOM_BACKGROUND_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;
+}
+
+static void CreateTextInputGadgets()
+{
+ int max_infotext_len = getMaxInfoTextLength();
+ int i;
+
+ for (i=0; i<ED_NUM_TEXTINPUT; 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 = textinput_info[i].gadget_id;
+
+ event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
+
+ gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
+ gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
+
+ sprintf(infotext, "Enter %s", textinput_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 + textinput_info[i].x,
+ GDI_Y, SY + textinput_info[i].y,
+ 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_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_EVENT_MASK, event_mask,
+ GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
+ GDI_CALLBACK_ACTION, HandleTextInputGadgets,
+ GDI_END);
+
+ if (gi == NULL)
+ Error(ERR_EXIT, "cannot create gadget");
+
+ level_editor_gadget[id] = gi;
+ }
+}
+
+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_VALUES, selectbox_info[i].values,
+ GDI_SELECTBOX_INDEX, selectbox_info[i].index,
+ GDI_TEXT_SIZE, selectbox_info[i].size,
+ GDI_TEXT_FONT, FONT_INPUT,
+ 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_BORDER_SIZE_SELECTBUTTON, getFontHeight(FONT_INPUT),
+ GDI_TEXTINPUT_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 CreateScrollbarGadgets()
+{
+ int i;
+
+ for (i=0; i<ED_NUM_SCROLLBARS; i++)
+ {
+ int id = scrollbar_info[i].gadget_id;
+ Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
+ int gd_x1, gd_x2, gd_y1, gd_y2;
+ struct GadgetInfo *gi;
+ int items_max, items_visible, item_position;
+ unsigned long event_mask;
+
+ if (i == ED_SCROLLBAR_ID_LIST_VERTICAL)
+ {
+ items_max = num_editor_elements / ED_ELEMENTLIST_BUTTONS_HORIZ;
+ items_visible = ED_ELEMENTLIST_BUTTONS_VERT;
+ item_position = 0;
+ }
+ else /* drawing area scrollbars */
+ {
+ if (scrollbar_info[i].type == GD_TYPE_SCROLLBAR_HORIZONTAL)
+ {
+ items_max = MAX(lev_fieldx + 2, ed_fieldx);
+ items_visible = ed_fieldx;
+ item_position = 0;
+ }
+ else
+ {
+ items_max = MAX(lev_fieldy + 2, ed_fieldy);
+ items_visible = ed_fieldy;
+ item_position = 0;
+ }
+ }
+
+ event_mask = GD_EVENT_MOVING | GD_EVENT_OFF_BORDERS;
+
+ gd_x1 = DOOR_GFX_PAGEX8 + scrollbar_info[i].xpos;
+ gd_x2 = (gd_x1 - (scrollbar_info[i].type == GD_TYPE_SCROLLBAR_HORIZONTAL ?
+ scrollbar_info[i].height : scrollbar_info[i].width));
+ gd_y1 = DOOR_GFX_PAGEY1 + scrollbar_info[i].ypos;
+ gd_y2 = DOOR_GFX_PAGEY1 + scrollbar_info[i].ypos;
+
+ gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_CUSTOM_TYPE_ID, i,
+ GDI_INFO_TEXT, scrollbar_info[i].infotext,
+ GDI_X, scrollbar_info[i].x,
+ GDI_Y, scrollbar_info[i].y,
+ GDI_WIDTH, scrollbar_info[i].width,
+ GDI_HEIGHT, scrollbar_info[i].height,
+ GDI_TYPE, scrollbar_info[i].type,
+ GDI_SCROLLBAR_ITEMS_MAX, items_max,
+ GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
+ GDI_SCROLLBAR_ITEM_POSITION, item_position,
+ 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_EVENT_MASK, event_mask,
+ GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
+ GDI_CALLBACK_ACTION, HandleControlButtons,
+ GDI_END);
+
+ if (gi == NULL)
+ Error(ERR_EXIT, "cannot create gadget");
+
+ level_editor_gadget[id] = gi;
+ }
+}
+
+static void CreateCheckbuttonGadgets()
+{
+ Bitmap *gd_bitmap = graphic_info[IMG_GLOBAL_DOOR].bitmap;
+ struct GadgetInfo *gi;
+ unsigned long event_mask;
+ int gd_x1, gd_x2, gd_x3, gd_x4, gd_y;
+ boolean checked;
+ int i;
+
+ event_mask = GD_EVENT_PRESSED;
+
+ gd_x1 = DOOR_GFX_PAGEX4 + ED_CHECKBUTTON_UNCHECKED_XPOS;
+ gd_x2 = DOOR_GFX_PAGEX3 + ED_CHECKBUTTON_UNCHECKED_XPOS;
+ gd_x3 = DOOR_GFX_PAGEX4 + ED_CHECKBUTTON_CHECKED_XPOS;
+ gd_x4 = DOOR_GFX_PAGEX3 + ED_CHECKBUTTON_CHECKED_XPOS;
+ gd_y = DOOR_GFX_PAGEY1 + ED_RADIOBUTTON_YPOS;
+
+ for (i=0; i<ED_NUM_RADIOBUTTONS; i++)
+ {
+ int id = radiobutton_info[i].gadget_id;
+
+ checked =
+ (*radiobutton_info[i].value == radiobutton_info[i].checked_value);
+
+ gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_CUSTOM_TYPE_ID, i,
+ GDI_INFO_TEXT, radiobutton_info[i].infotext,
+ GDI_X, SX + radiobutton_info[i].x,
+ GDI_Y, SY + radiobutton_info[i].y,
+ GDI_WIDTH, ED_CHECKBUTTON_XSIZE,
+ GDI_HEIGHT, ED_CHECKBUTTON_YSIZE,
+ GDI_TYPE, GD_TYPE_RADIO_BUTTON,
+ GDI_RADIO_NR, radiobutton_info[i].radio_button_nr,
+ GDI_CHECKED, checked,
+ GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
+ GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
+ GDI_ALT_DESIGN_UNPRESSED, gd_bitmap, gd_x3, gd_y,
+ GDI_ALT_DESIGN_PRESSED, gd_bitmap, gd_x4, gd_y,
+ GDI_EVENT_MASK, event_mask,
+ GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
+ GDI_CALLBACK_ACTION, HandleRadiobuttons,
+ GDI_END);
+
+ if (gi == NULL)
+ Error(ERR_EXIT, "cannot create gadget");
+
+ level_editor_gadget[id] = gi;
+ }
+
+ for (i=0; i<ED_NUM_CHECKBUTTONS; i++)
+ {
+ int id = checkbutton_info[i].gadget_id;
+
+ if (id == GADGET_ID_STICK_ELEMENT)
+ gd_y = DOOR_GFX_PAGEY1 + ED_STICKYBUTTON_YPOS;
+ else
+ gd_y = DOOR_GFX_PAGEY1 + ED_CHECKBUTTON_YPOS;
+
+ gi = CreateGadget(GDI_CUSTOM_ID, id,
+ GDI_CUSTOM_TYPE_ID, i,
+ GDI_INFO_TEXT, checkbutton_info[i].infotext,
+ GDI_X, SX + checkbutton_info[i].x,
+ GDI_Y, SY + checkbutton_info[i].y,
+ GDI_WIDTH, ED_CHECKBUTTON_XSIZE,
+ GDI_HEIGHT, ED_CHECKBUTTON_YSIZE,
+ GDI_TYPE, GD_TYPE_CHECK_BUTTON,
+ GDI_CHECKED, *checkbutton_info[i].value,
+ GDI_DESIGN_UNPRESSED, gd_bitmap, gd_x1, gd_y,
+ GDI_DESIGN_PRESSED, gd_bitmap, gd_x2, gd_y,
+ GDI_ALT_DESIGN_UNPRESSED, gd_bitmap, gd_x3, gd_y,
+ GDI_ALT_DESIGN_PRESSED, gd_bitmap, gd_x4, gd_y,
+ GDI_EVENT_MASK, event_mask,
+ GDI_CALLBACK_INFO, HandleEditorGadgetInfoText,
+ GDI_CALLBACK_ACTION, HandleCheckbuttons,
+ GDI_END);
+
+ if (gi == NULL)
+ Error(ERR_EXIT, "cannot create gadget");
+
+ level_editor_gadget[id] = gi;
+ }
+}
+
+void CreateLevelEditorGadgets()
+{
+ ReinitializeElementList();
+
+ CreateControlButtons();
+ CreateCounterButtons();
+ CreateDrawingAreas();
+ CreateTextInputGadgets();
+ CreateSelectboxGadgets();
+ CreateScrollbarGadgets();
+ CreateCheckbuttonGadgets();
+}
+
+void FreeLevelEditorGadgets()
+{
+ int i;
+
+ for (i=0; i<NUM_EDITOR_GADGETS; i++)
+ FreeGadget(level_editor_gadget[i]);
+}
+
+static void MapCounterButtons(int id)
+{
+ MapGadget(level_editor_gadget[counterbutton_info[id].gadget_id_down]);
+ MapGadget(level_editor_gadget[counterbutton_info[id].gadget_id_text]);
+ MapGadget(level_editor_gadget[counterbutton_info[id].gadget_id_up]);
+}
+
+static void MapControlButtons()
+{
+ int counter_id;
+ int i;
+
+ /* map toolbox buttons */
+ for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
+ MapGadget(level_editor_gadget[i]);
+
+ /* map buttons to select elements */
+ for (i=0; i<ED_NUM_ELEMENTLIST_BUTTONS; i++)
+ MapGadget(level_editor_gadget[GADGET_ID_ELEMENTLIST_FIRST + i]);
+ MapGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_VERTICAL]);
+ MapGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_UP]);
+ MapGadget(level_editor_gadget[GADGET_ID_SCROLL_LIST_DOWN]);
+
+ /* map buttons to select level */
+ counter_id = ED_COUNTER_ID_SELECT_LEVEL;
+ ModifyEditorCounterLimits(counter_id,
+ leveldir_current->first_level,
+ leveldir_current->last_level);
+ ModifyEditorCounter(counter_id, *counterbutton_info[counter_id].value);
+ MapCounterButtons(counter_id);
+}
+
+static void MapDrawingArea(int id)
+{
+ MapGadget(level_editor_gadget[id]);
+}
+
+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 MapRadiobuttonGadget(int id)
+{
+ MapGadget(level_editor_gadget[radiobutton_info[id].gadget_id]);
+}
+
+static void MapCheckbuttonGadget(int id)
+{
+ MapGadget(level_editor_gadget[checkbutton_info[id].gadget_id]);
+}
+
+static void MapMainDrawingArea()
+{
+ boolean no_horizontal_scrollbar = (lev_fieldx + 2 <= ed_fieldx);
+ boolean no_vertical_scrollbar = (lev_fieldy + 2 <= ed_fieldy);
+ int i;
+
+ for (i=ED_SCROLLBUTTON_ID_AREA_FIRST; i<=ED_SCROLLBUTTON_ID_AREA_LAST; i++)
+ {
+ if (((i == ED_SCROLLBUTTON_ID_AREA_LEFT ||
+ i == ED_SCROLLBUTTON_ID_AREA_RIGHT) &&
+ no_horizontal_scrollbar) ||
+ ((i == ED_SCROLLBUTTON_ID_AREA_UP ||
+ i == ED_SCROLLBUTTON_ID_AREA_DOWN) &&
+ no_vertical_scrollbar))
+ continue;
+
+ MapGadget(level_editor_gadget[scrollbutton_info[i].gadget_id]);
+ }
+
+ for (i=ED_SCROLLBAR_ID_AREA_FIRST; i<=ED_SCROLLBAR_ID_AREA_LAST; i++)
+ {
+ if ((i == ED_SCROLLBAR_ID_AREA_HORIZONTAL && no_horizontal_scrollbar) ||
+ (i == ED_SCROLLBAR_ID_AREA_VERTICAL && no_vertical_scrollbar))
+ continue;
+
+ MapGadget(level_editor_gadget[scrollbar_info[i].gadget_id]);
+ }
+
+ MapDrawingArea(GADGET_ID_DRAWING_LEVEL);
+}
+
+static void UnmapDrawingArea(int id)
+{
+ UnmapGadget(level_editor_gadget[id]);
+}
+
+void UnmapLevelEditorWindowGadgets()
+{
+ int i;
+
+ for (i=0; i<NUM_EDITOR_GADGETS; i++)
+ if (level_editor_gadget[i]->x < SX + SXSIZE)
+ UnmapGadget(level_editor_gadget[i]);
+}
+
+void UnmapLevelEditorGadgets()
+{
+ int i;
+
+ for (i=0; i<NUM_EDITOR_GADGETS; i++)
+ UnmapGadget(level_editor_gadget[i]);
+}
+
+static void ResetUndoBuffer()
+{
+ undo_buffer_position = -1;
+ undo_buffer_steps = -1;
+ CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
+}
+
+static void DrawEditModeWindow()
+{
+ if (edit_mode == ED_MODE_INFO)
+ DrawLevelInfoWindow();
+ else if (edit_mode == ED_MODE_PROPERTIES)
+ DrawPropertiesWindow();
+ else /* edit_mode == ED_MODE_DRAWING */
+ DrawDrawingWindow();
+}
+
+static boolean LevelChanged()
+{
+ boolean level_changed = FALSE;
+ int x, y;
+
+ for(y=0; y<lev_fieldy; y++)
+ for(x=0; x<lev_fieldx; x++)
+ if (Feld[x][y] != Ur[x][y])
+ level_changed = TRUE;
+
+ return level_changed;
+}
+
+static boolean LevelContainsPlayer()
+{
+ boolean player_found = FALSE;
+ int x, y;
+
+ for(y=0; y<lev_fieldy; y++)
+ for(x=0; x<lev_fieldx; x++)
+ if (Feld[x][y] == EL_PLAYER_1 ||
+ Feld[x][y] == EL_SP_MURPHY)
+ player_found = TRUE;
+
+ return player_found;
+}
+
+static void CopyPlayfield(short src[MAX_LEV_FIELDX][MAX_LEV_FIELDY],
+ short dst[MAX_LEV_FIELDX][MAX_LEV_FIELDY])
+{
+ int x, y;
+
+ for(x=0; x<lev_fieldx; x++)
+ for(y=0; y<lev_fieldy; y++)
+ dst[x][y] = src[x][y];
+}
+
+static void CopyCustomElementPropertiesToEditor()
+{
+ 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);
+ }
+}
+
+static void CopyCustomElementPropertiesToGame()
+{
+ 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;
+ }
+}
+
+void DrawLevelEd()
+{
+ CloseDoor(DOOR_CLOSE_ALL);
+ OpenDoor(DOOR_OPEN_2 | DOOR_NO_DELAY);
+
+ if (level_editor_test_game)
+ {
+ CopyPlayfield(Ur, Feld);
+ CopyPlayfield(FieldBackup, Ur);
+
+ level_editor_test_game = FALSE;
+ }
+ else
+ {
+ edit_mode = ED_MODE_DRAWING;
+
+ ResetUndoBuffer();
+ level_xpos = -1;
+ level_ypos = -1;
+ }
+
+ /* copy default editor door content to main double buffer */
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ DOOR_GFX_PAGEX6, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, DX, DY);
+
+ /* draw mouse button brush elements */
+ DrawMiniGraphicExt(drawto,
+ DX + ED_WIN_MB_LEFT_XPOS, DY + ED_WIN_MB_LEFT_YPOS,
+ el2edimg(new_element1));
+ DrawMiniGraphicExt(drawto,
+ DX + ED_WIN_MB_MIDDLE_XPOS, DY + ED_WIN_MB_MIDDLE_YPOS,
+ el2edimg(new_element2));
+ DrawMiniGraphicExt(drawto,
+ DX + ED_WIN_MB_RIGHT_XPOS, DY + ED_WIN_MB_RIGHT_YPOS,
+ el2edimg(new_element3));
+
+ /* draw bigger door */
+ DrawSpecialEditorDoor();
+
+ /* draw new control window */
+ BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, drawto,
+ DOOR_GFX_PAGEX8, 236, EXSIZE, EYSIZE, EX, EY);
+
+ redraw_mask |= REDRAW_ALL;
+
+ ReinitializeElementListButtons(); /* only needed after setup changes */
+
+ UnmapTapeButtons();
+ MapControlButtons();
+
+ /* copy actual editor door content to door double buffer for OpenDoor() */
+ BlitBitmap(drawto, bitmap_db_door,
+ DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
+
+ DrawEditModeWindow();
+
+ OpenDoor(DOOR_OPEN_1);
+}
+
+static void AdjustDrawingAreaGadgets()
+{
+ int ed_xsize = lev_fieldx + 2;
+ int ed_ysize = lev_fieldy + 2;
+ int max_ed_fieldx = MAX_ED_FIELDX;
+ int max_ed_fieldy = MAX_ED_FIELDY;
+ boolean horizontal_scrollbar_needed;
+ boolean vertical_scrollbar_needed;
+ int x, y, width, height;
+ int xoffset, yoffset;
+
+ /* check if we need any scrollbars */
+ horizontal_scrollbar_needed = (ed_xsize > max_ed_fieldx);
+ vertical_scrollbar_needed = (ed_ysize > max_ed_fieldy);
+
+ /* check if we have a smaller editor field because of scrollbars */
+ if (horizontal_scrollbar_needed)
+ max_ed_fieldy = MAX_ED_FIELDY - 1;
+ if (vertical_scrollbar_needed)
+ max_ed_fieldx = MAX_ED_FIELDX - 1;
+
+ /* check again if we now need more scrollbars because of less space */
+ horizontal_scrollbar_needed = (ed_xsize > max_ed_fieldx);
+ vertical_scrollbar_needed = (ed_ysize > max_ed_fieldy);
+
+ /* check if editor field gets even smaller after adding new scrollbars */
+ if (horizontal_scrollbar_needed)
+ max_ed_fieldy = MAX_ED_FIELDY - 1;
+ if (vertical_scrollbar_needed)
+ max_ed_fieldx = MAX_ED_FIELDX - 1;
+
+ ed_fieldx = (ed_xsize < MAX_ED_FIELDX ? ed_xsize : max_ed_fieldx);
+ 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);
+
+ xoffset = (ed_fieldx == MAX_ED_FIELDX ? ED_SCROLLBUTTON_XSIZE : 0);
+ yoffset = (ed_fieldy == MAX_ED_FIELDY ? ED_SCROLLBUTTON_YSIZE : 0);
+
+ x = SX + scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_RIGHT].x + xoffset;
+ y = SX + scrollbutton_info[ED_SCROLLBUTTON_ID_AREA_DOWN].y + yoffset;
+
+ ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_RIGHT], GDI_X, x, GDI_END);
+ ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_DOWN], GDI_Y, y, GDI_END);
+
+ width = scrollbar_info[ED_SCROLLBAR_ID_AREA_HORIZONTAL].width + xoffset;
+ height = scrollbar_info[ED_SCROLLBAR_ID_AREA_VERTICAL].height + yoffset;
+
+ ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_HORIZONTAL],
+ GDI_WIDTH, width,
+ GDI_SCROLLBAR_ITEMS_VISIBLE, ed_fieldx,
+ GDI_END);
+ ModifyGadget(level_editor_gadget[GADGET_ID_SCROLL_VERTICAL],
+ GDI_HEIGHT, height,
+ GDI_SCROLLBAR_ITEMS_VISIBLE, ed_fieldy,
+ GDI_END);
+}
+
+static void AdjustLevelScrollPosition()
+{
+ if (level_xpos < -1)
+ level_xpos = -1;
+ if (level_xpos > lev_fieldx - ed_fieldx + 1)
+ level_xpos = lev_fieldx - ed_fieldx + 1;
+ if (lev_fieldx < ed_fieldx - 2)
+ level_xpos = -1;
+
+ if (level_ypos < -1)
+ level_ypos = -1;
+ if (level_ypos > lev_fieldy - ed_fieldy + 1)
+ level_ypos = lev_fieldy - ed_fieldy + 1;
+ if (lev_fieldy < ed_fieldy - 2)
+ level_ypos = -1;
+}
+
+static void AdjustEditorScrollbar(int id)
+{
+ struct GadgetInfo *gi = level_editor_gadget[id];
+ int items_max, items_visible, item_position;
+
+ if (id == GADGET_ID_SCROLL_HORIZONTAL)
+ {
+ items_max = MAX(lev_fieldx + 2, ed_fieldx);
+ items_visible = ed_fieldx;
+ item_position = level_xpos + 1;
+ }
+ else
+ {
+ items_max = MAX(lev_fieldy + 2, ed_fieldy);
+ items_visible = ed_fieldy;
+ item_position = level_ypos + 1;
+ }
+
+ if (item_position > items_max - items_visible)
+ item_position = items_max - items_visible;
+
+ ModifyGadget(gi, GDI_SCROLLBAR_ITEMS_MAX, items_max,
+ GDI_SCROLLBAR_ITEM_POSITION, item_position, GDI_END);
+}
+
+static void ModifyEditorTextInput(int textinput_id, char *new_text)
+{
+ int gadget_id = textinput_info[textinput_id].gadget_id;
+ struct GadgetInfo *gi = level_editor_gadget[gadget_id];
+
+ ModifyGadget(gi, GDI_TEXT_VALUE, new_text, GDI_END);
+}
+
+static void ModifyEditorCounter(int counter_id, int new_value)
+{
+ int *counter_value = counterbutton_info[counter_id].value;
+ int gadget_id = counterbutton_info[counter_id].gadget_id_text;
+ struct GadgetInfo *gi = level_editor_gadget[gadget_id];
+
+ ModifyGadget(gi, GDI_NUMBER_VALUE, new_value, GDI_END);
+
+ if (counter_value != NULL)
+ *counter_value = gi->text.number_value;
+}
+
+static void ModifyEditorCounterLimits(int counter_id, int min, int max)
+{
+ int gadget_id = counterbutton_info[counter_id].gadget_id_text;
+ struct GadgetInfo *gi = level_editor_gadget[gadget_id];
+
+ ModifyGadget(gi, GDI_NUMBER_MIN, min, GDI_NUMBER_MAX, max, GDI_END);
+}
+
+static void PickDrawingElement(int button, int element)
+{
+ 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));
+ }
+
+ redraw_mask |= REDRAW_DOOR_1;
+}
+
+static void DrawDrawingWindow()
+{
+ SetMainBackgroundImage(IMG_UNDEFINED);
+ ClearWindow();
+ UnmapLevelEditorWindowGadgets();
+
+ AdjustDrawingAreaGadgets();
+ AdjustLevelScrollPosition();
+ AdjustEditorScrollbar(GADGET_ID_SCROLL_HORIZONTAL);
+ AdjustEditorScrollbar(GADGET_ID_SCROLL_VERTICAL);
+
+ DrawMiniLevel(ed_fieldx, ed_fieldy, level_xpos, level_ypos);
+ MapMainDrawingArea();
+}
+
+static void DrawElementBorder(int dest_x, int dest_y, int width, int height)
+{
+ int border_graphic = IMG_EDITOR_ELEMENT_BORDER;
+ Bitmap *src_bitmap;
+ int src_x, src_y;
+ int num_mini_tilex = width / MINI_TILEX + 1;
+ int num_mini_tiley = width / MINI_TILEY + 1;
+ int x, y;
+
+ getMiniGraphicSource(border_graphic, &src_bitmap, &src_x, &src_y);
+
+ for (y=0; y < num_mini_tiley; y++)
+ for (x=0; x < num_mini_tilex; x++)
+ BlitBitmap(src_bitmap, drawto, src_x, src_y, MINI_TILEX, MINI_TILEY,
+ dest_x - MINI_TILEX / 2 + x * MINI_TILEX,
+ dest_y - MINI_TILEY / 2 + y * MINI_TILEY);
+
+ ClearRectangle(drawto, dest_x - 1, dest_y - 1, width + 2, height + 2);
+}
+
+static void DrawRandomPlacementBackgroundArea()
+{
+ int area_x = ED_AREA_RANDOM_BACKGROUND_XPOS / MINI_TILEX;
+ int area_y = ED_AREA_RANDOM_BACKGROUND_YPOS / MINI_TILEY;
+ int area_sx = SX + ED_AREA_RANDOM_BACKGROUND_XPOS;
+ int area_sy = SY + ED_AREA_RANDOM_BACKGROUND_YPOS;
+
+ ElementContent[0][0][0] = random_placement_background_element;
+
+ DrawElementBorder(area_sx, area_sy, MINI_TILEX, MINI_TILEY);
+ DrawMiniElement(area_x, area_y, ElementContent[0][0][0]);
+
+ MapDrawingArea(GADGET_ID_RANDOM_BACKGROUND);
+}
+
+static void DrawLevelInfoWindow()
+{
+ char infotext[MAX_OUTPUT_LINESIZE + 1];
+ int max_infotext_len = getMaxInfoTextLength();
+ int xoffset_above = 0;
+ int yoffset_above = -(MINI_TILEX + ED_GADGET_DISTANCE);
+ 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 i, x, y;
+
+ SetMainBackgroundImage(IMG_BACKGROUND_EDITOR);
+ ClearWindow();
+ UnmapLevelEditorWindowGadgets();
+
+ DrawText(SX + ED_SETTINGS2_XPOS, SY + ED_SETTINGS_YPOS,
+ "Level Settings", FONT_TITLE_1);
+ DrawText(SX + ED_SETTINGS2_XPOS, SY + ED_SETTINGS2_YPOS,
+ "Editor Settings", FONT_TITLE_1);
+
+ /* draw counter gadgets */
+ for (i=ED_COUNTER_ID_LEVEL_FIRST; i<=ED_COUNTER_ID_LEVEL_LAST; i++)
+ {
+ if (counterbutton_info[i].infotext_above)
+ {
+ x = counterbutton_info[i].x + xoffset_above;
+ y = counterbutton_info[i].y + yoffset_above;
+
+ sprintf(infotext, "%s:", counterbutton_info[i].infotext_above);
+ infotext[max_infotext_len] = '\0';
+ DrawTextF(x, y, FONT_TEXT_1, infotext);
+ }
+
+ if (counterbutton_info[i].infotext_right)
+ {
+ x = counterbutton_info[i].x + xoffset_right;
+ y = counterbutton_info[i].y + yoffset_right;
+
+ sprintf(infotext, "%s", counterbutton_info[i].infotext_right);
+ infotext[max_infotext_len] = '\0';
+ DrawTextF(x, y, FONT_TEXT_1, infotext);
+ }
+
+ ModifyEditorCounter(i, *counterbutton_info[i].value);
+ MapCounterButtons(i);
+ }
+
+ /* draw text input gadgets */
+ for (i=ED_TEXTINPUT_ID_LEVEL_FIRST; i<=ED_TEXTINPUT_ID_LEVEL_LAST; i++)
+ {
+ x = textinput_info[i].x + xoffset_above;
+ y = textinput_info[i].y + yoffset_above;
+
+ sprintf(infotext, "%s:", textinput_info[i].infotext);
+ infotext[max_infotext_len] = '\0';
+
+ DrawTextF(x, y, FONT_TEXT_1, infotext);
+ ModifyEditorTextInput(i, textinput_info[i].value);
+ MapTextInputGadget(i);
+ }
+
+ /* draw radiobutton gadgets */
+ for (i=ED_RADIOBUTTON_ID_LEVEL_FIRST; i<=ED_RADIOBUTTON_ID_LEVEL_LAST; i++)
+ {
+ boolean checked =
+ (*radiobutton_info[i].value == radiobutton_info[i].checked_value);
+
+ x = radiobutton_info[i].x + xoffset_right2;
+ y = radiobutton_info[i].y + yoffset_right2;
+
+ DrawTextF(x, y, FONT_TEXT_1, radiobutton_info[i].text);
+ ModifyGadget(level_editor_gadget[radiobutton_info[i].gadget_id],
+ GDI_CHECKED, checked, GDI_END);
+ MapRadiobuttonGadget(i);
+ }
+
+ /* draw checkbutton gadgets */
+ for (i=ED_CHECKBUTTON_ID_LEVEL_FIRST; i<=ED_CHECKBUTTON_ID_LEVEL_LAST; i++)
+ {
+ 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 drawing area */
+ DrawRandomPlacementBackgroundArea();
+}
+
+static void DrawAmoebaContentArea()
+{
+ int area_x = ED_AREA_ELEM_CONTENT_XPOS / MINI_TILEX;
+ int area_y = ED_AREA_ELEM_CONTENT_YPOS / MINI_TILEY;
+ int area_sx = SX + ED_AREA_ELEM_CONTENT_XPOS;
+ int area_sy = SY + ED_AREA_ELEM_CONTENT_YPOS;
+
+ ElementContent[0][0][0] = level.amoeba_content;
+
+ 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, "Content of amoeba", FONT_TEXT_1);
+
+ MapDrawingArea(GADGET_ID_AMOEBA_CONTENT);
+}
+
+static void DrawElementContentAreas()
+{
+ int counter_id = ED_COUNTER_ID_ELEM_CONTENT;
+ int area_x = ED_AREA_ELEM_CONTENT_XPOS / MINI_TILEX;
+ int area_y = ED_AREA_ELEM_CONTENT_YPOS / MINI_TILEY;
+ int area_sx = SX + ED_AREA_ELEM_CONTENT_XPOS;
+ int area_sy = SY + ED_AREA_ELEM_CONTENT_YPOS;
+ int xoffset_right = getCounterGadgetWidth();
+ int yoffset_right = ED_BORDER_SIZE;
+ int i, x, y;
+
+ for (i=0; i<MAX_ELEMENT_CONTENTS; i++)
+ for (y=0; y<3; y++)
+ for (x=0; x<3; x++)
+ ElementContent[i][x][y] = level.yam_content[i][x][y];
+
+ for (i=0; i<MAX_ELEMENT_CONTENTS; i++)
+ UnmapDrawingArea(GADGET_ID_ELEM_CONTENT_0 + i);
+
+ /* display counter to choose number of element content areas */
+ x = counterbutton_info[counter_id].x + xoffset_right;
+ y = counterbutton_info[counter_id].y + yoffset_right;
+ DrawTextF(x, y, FONT_TEXT_1, "number of content areas");
+
+ ModifyEditorCounter(counter_id, *counterbutton_info[counter_id].value);
+ MapCounterButtons(counter_id);
+
+ /* delete content areas in case of reducing number of them */
+ DrawBackground(SX, area_sy - MINI_TILEX, SXSIZE, 12 * MINI_TILEY);
+
+ for (i=0; i<level.num_yam_contents; i++)
+ DrawElementBorder(area_sx + 5 * (i % 4) * MINI_TILEX,
+ area_sy + 6 * (i / 4) * MINI_TILEY,
+ 3 * MINI_TILEX, 3 * MINI_TILEY);
+
+ DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 0 * MINI_TILEY + 1,
+ "Content", FONT_TEXT_1);
+ DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 1 * MINI_TILEY + 1,
+ "when", FONT_TEXT_1);
+ DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 2 * MINI_TILEY + 1,
+ "smashed", FONT_TEXT_1);
+
+ for (i=0; i<level.num_yam_contents; i++)
+ {
+ for (y=0; y<3; y++)
+ for (x=0; x<3; x++)
+ DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
+ ElementContent[i][x][y]);
+
+ DrawTextF(area_sx - SX + 5 * (i % 4) * MINI_TILEX + MINI_TILEX + 1,
+ area_sy - SY + 6 * (i / 4) * MINI_TILEY + 4 * MINI_TILEY - 4,
+ FONT_TEXT_1, "%d", i + 1);
+ }
+
+ for (i=0; i<level.num_yam_contents; i++)
+ MapDrawingArea(GADGET_ID_ELEM_CONTENT_0 + i);
+}
+
+#define TEXT_COLLECTING "Score for collecting"
+#define TEXT_SMASHING "Score for smashing"
+#define TEXT_CRACKING "Score for cracking"
+#define TEXT_SPEED "Speed of amoeba growth"
+#define TEXT_DURATION "Duration when activated"
+
+static void DrawPropertiesWindow()
+{
+ 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++)
+ {
+ if (elements_with_counter[i].element == properties_element)
+ {
+ int x = counterbutton_info[counter_id].x + xoffset_right;
+ int y = counterbutton_info[counter_id].y + yoffset_right;
+
+ counterbutton_info[counter_id].value = elements_with_counter[i].value;
+ DrawTextF(x, y, FONT_TEXT_1, elements_with_counter[i].text);
+
+ ModifyEditorCounter(counter_id, *counterbutton_info[counter_id].value);
+ MapCounterButtons(counter_id);
+ break;
+ }
+ }
+
+ if (HAS_CONTENT(properties_element))
+ {
+ /* draw stickybutton gadget */
+ i = ED_CHECKBUTTON_ID_STICK_ELEMENT;
+ 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);
+
+ if (IS_AMOEBOID(properties_element))
+ DrawAmoebaContentArea();
+ else
+ DrawElementContentAreas();
+ }
+
+ if (IS_GEM(properties_element))
+ {
+ /* draw checkbutton gadget */
+ i = ED_CHECKBUTTON_ID_EM_SLIPPERY_GEMS;
+ 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);
+ }
+
+ if (IS_CUSTOM_ELEMENT(properties_element))
+ {
+ int nr = properties_element - EL_CUSTOM_START;
+
+ CopyCustomElementPropertiesToEditor();
+
+ /* draw checkbutton gadget */
+ i = ED_CHECKBUTTON_ID_CUSTOM_INDESTRUCTIBLE;
+ x = checkbutton_info[i].x + xoffset_right2;
+ y = checkbutton_info[i].y + yoffset_right2;
+
+ checkbutton_info[i].value = &custom_element_properties[nr].indestructible;
+
+ 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_CAN_FALL;
+ x = checkbutton_info[i].x + xoffset_right2;
+ y = checkbutton_info[i].y + yoffset_right2;
+
+ checkbutton_info[i].value = &custom_element_properties[nr].can_fall;
+
+ 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);