+#include "buttons.h"
+#include "files.h"
+#include "game.h"
+#include "tape.h"
+
+/* positions in the level editor */
+#define ED_WIN_MB_LEFT_XPOS 7
+#define ED_WIN_MB_LEFT_YPOS 6
+#define ED_WIN_LEVELNR_XPOS 77
+#define ED_WIN_LEVELNR_YPOS 7
+#define ED_WIN_MB_MIDDLE_XPOS 7
+#define ED_WIN_MB_MIDDLE_YPOS 258
+#define ED_WIN_MB_RIGHT_XPOS 77
+#define ED_WIN_MB_RIGHT_YPOS 258
+
+/* other constants for the editor */
+#define ED_SCROLL_NO 0
+#define ED_SCROLL_LEFT 1
+#define ED_SCROLL_RIGHT 2
+#define ED_SCROLL_UP 4
+#define ED_SCROLL_DOWN 8
+
+/* screens in the level editor */
+#define ED_MODE_DRAWING 0
+#define ED_MODE_INFO 1
+#define ED_MODE_PROPERTIES 2
+
+/* how many steps can be cancelled */
+#define NUM_UNDO_STEPS (10 + 1)
+
+/* values for random placement */
+#define RANDOM_USE_PERCENTAGE 0
+#define RANDOM_USE_NUM_OBJECTS 1
+
+/* values for elements with score */
+#define MIN_SCORE 0
+#define MAX_SCORE 255
+
+/* values for elements with content */
+#define MIN_ELEM_CONTENT 1
+#define MAX_ELEM_CONTENT 8
+
+/* values for the control window */
+#define ED_CTRL_BUTTONS_GFX_YPOS 236
+#define ED_CTRL_BUTTONS_ALT_GFX_YPOS 142
+
+#define ED_CTRL1_BUTTONS_HORIZ 4
+#define ED_CTRL1_BUTTONS_VERT 4
+#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_BUTTONS_HORIZ 3
+#define ED_CTRL2_BUTTONS_VERT 2
+#define ED_CTRL2_BUTTON_XSIZE 30
+#define ED_CTRL2_BUTTON_YSIZE 20
+#define ED_CTRL2_BUTTONS_XPOS 5
+#define ED_CTRL2_BUTTONS_YPOS 100
+#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_CTRL_BUTTONS (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS)
+
+/* values for element properties window */
+#define ED_PROPERTIES_XPOS (TILEX - MINI_TILEX/2)
+
+/* values for level information window */
+#define ED_LEVELINFO_XPOS (TILEX - MINI_TILEX/2)
+#define ED_LEVELINFO_YPOS (TILEY - MINI_TILEY/2)
+
+/* values for counter gadgets */
+#define ED_COUNT_VALUE_XOFFSET 5
+#define ED_COUNT_VALUE_YOFFSET 3
+#define ED_COUNT_ELEM_SCORE_XPOS ED_PROPERTIES_XPOS
+#define ED_COUNT_ELEM_SCORE_YPOS (14 * MINI_TILEY)
+#define ED_COUNT_ELEM_CONTENT_XPOS ED_PROPERTIES_XPOS
+#define ED_COUNT_ELEM_CONTENT_YPOS (17 * MINI_TILEY)
+#define ED_COUNTER_YSTART (ED_LEVELINFO_YPOS + 3 * TILEY)
+#define ED_COUNTER_YDISTANCE (3 * MINI_TILEY)
+#define ED_COUNTER_YPOS(n) (ED_COUNTER_YSTART + \
+ n * ED_COUNTER_YDISTANCE)
+/* standard distances */
+#define ED_BORDER_SIZE 3
+#define ED_GADGET_DISTANCE 2
+
+/* values for element content drawing areas */
+#define ED_AREA_ELEM_CONTENT_XPOS (TILEX)
+#define ED_AREA_ELEM_CONTENT_YPOS (10 * TILEY)
+
+/* values for scrolling gadgets */
+#define ED_SCROLLBUTTON_XPOS 24
+#define ED_SCROLLBUTTON_YPOS 0
+#define ED_SCROLLBAR_XPOS 24
+#define ED_SCROLLBAR_YPOS 64
+
+#define ED_SCROLLBUTTON_XSIZE 16
+#define ED_SCROLLBUTTON_YSIZE 16
+
+#define ED_SCROLL_UP_XPOS (SXSIZE - ED_SCROLLBUTTON_XSIZE)
+#define ED_SCROLL_UP_YPOS (0)
+#define ED_SCROLL_DOWN_XPOS ED_SCROLL_UP_XPOS
+#define ED_SCROLL_DOWN_YPOS (SYSIZE - 3 * ED_SCROLLBUTTON_YSIZE)
+#define ED_SCROLL_LEFT_XPOS (0)
+#define ED_SCROLL_LEFT_YPOS (SYSIZE - 2 * ED_SCROLLBUTTON_YSIZE)
+#define ED_SCROLL_RIGHT_XPOS (SXSIZE - 2 * ED_SCROLLBUTTON_XSIZE)
+#define ED_SCROLL_RIGHT_YPOS ED_SCROLL_LEFT_YPOS
+#define ED_SCROLL_VERTICAL_XPOS ED_SCROLL_UP_XPOS
+#define ED_SCROLL_VERTICAL_YPOS (ED_SCROLL_UP_YPOS + ED_SCROLLBUTTON_YSIZE)
+#define ED_SCROLL_VERTICAL_XSIZE ED_SCROLLBUTTON_XSIZE
+#define ED_SCROLL_VERTICAL_YSIZE (SYSIZE - 4 * ED_SCROLLBUTTON_YSIZE)
+#define ED_SCROLL_HORIZONTAL_XPOS (ED_SCROLL_LEFT_XPOS + ED_SCROLLBUTTON_XSIZE)
+#define ED_SCROLL_HORIZONTAL_YPOS ED_SCROLL_LEFT_YPOS
+#define ED_SCROLL_HORIZONTAL_XSIZE (SXSIZE - 3 * ED_SCROLLBUTTON_XSIZE)
+#define ED_SCROLL_HORIZONTAL_YSIZE ED_SCROLLBUTTON_YSIZE
+
+/* control button identifiers */
+#define ED_CTRL_ID_NONE -1
+
+#define ED_CTRL_ID_SINGLE_ITEMS 0
+#define ED_CTRL_ID_CONNECTED_ITEMS 1
+#define ED_CTRL_ID_LINE 2
+#define ED_CTRL_ID_TEXT 3
+#define ED_CTRL_ID_RECTANGLE 4
+#define ED_CTRL_ID_FILLED_BOX 5
+#define ED_CTRL_ID_WRAP_UP 6
+#define ED_CTRL_ID_PROPERTIES 7
+#define ED_CTRL_ID_FLOOD_FILL 8
+#define ED_CTRL_ID_WRAP_LEFT 9
+#define ED_CTRL_ID_UNUSED1 10
+#define ED_CTRL_ID_WRAP_RIGHT 11
+#define ED_CTRL_ID_RANDOM_PLACEMENT 12
+#define ED_CTRL_ID_GRAB_BRUSH 13
+#define ED_CTRL_ID_WRAP_DOWN 14
+#define ED_CTRL_ID_PICK_ELEMENT 15
+#define ED_CTRL_ID_UNDO 16
+#define ED_CTRL_ID_INFO 17
+#define ED_CTRL_ID_SAVE 18
+#define ED_CTRL_ID_CLEAR 19
+#define ED_CTRL_ID_TEST 20
+#define ED_CTRL_ID_EXIT 21
+
+/* counter button identifiers */
+#define ED_CTRL_ID_ELEM_SCORE_DOWN 22
+#define ED_CTRL_ID_ELEM_SCORE_TEXT 23
+#define ED_CTRL_ID_ELEM_SCORE_UP 24
+#define ED_CTRL_ID_ELEM_CONTENT_DOWN 25
+#define ED_CTRL_ID_ELEM_CONTENT_TEXT 26
+#define ED_CTRL_ID_ELEM_CONTENT_UP 27
+#define ED_CTRL_ID_LEVEL_XSIZE_DOWN 28
+#define ED_CTRL_ID_LEVEL_XSIZE_TEXT 29
+#define ED_CTRL_ID_LEVEL_XSIZE_UP 30
+#define ED_CTRL_ID_LEVEL_YSIZE_DOWN 31
+#define ED_CTRL_ID_LEVEL_YSIZE_TEXT 32
+#define ED_CTRL_ID_LEVEL_YSIZE_UP 33
+#define ED_CTRL_ID_LEVEL_RANDOM_DOWN 34
+#define ED_CTRL_ID_LEVEL_RANDOM_TEXT 35
+#define ED_CTRL_ID_LEVEL_RANDOM_UP 36
+#define ED_CTRL_ID_LEVEL_COLLECT_DOWN 37
+#define ED_CTRL_ID_LEVEL_COLLECT_TEXT 38
+#define ED_CTRL_ID_LEVEL_COLLECT_UP 39
+#define ED_CTRL_ID_LEVEL_TIMELIMIT_DOWN 40
+#define ED_CTRL_ID_LEVEL_TIMELIMIT_TEXT 41
+#define ED_CTRL_ID_LEVEL_TIMELIMIT_UP 42
+#define ED_CTRL_ID_LEVEL_TIMESCORE_DOWN 43
+#define ED_CTRL_ID_LEVEL_TIMESCORE_TEXT 44
+#define ED_CTRL_ID_LEVEL_TIMESCORE_UP 45
+
+/* drawing area identifiers */
+#define ED_CTRL_ID_DRAWING_LEVEL 46
+#define ED_CTRL_ID_ELEM_CONTENT_0 47
+#define ED_CTRL_ID_ELEM_CONTENT_1 48
+#define ED_CTRL_ID_ELEM_CONTENT_2 49
+#define ED_CTRL_ID_ELEM_CONTENT_3 50
+#define ED_CTRL_ID_ELEM_CONTENT_4 51
+#define ED_CTRL_ID_ELEM_CONTENT_5 52
+#define ED_CTRL_ID_ELEM_CONTENT_6 53
+#define ED_CTRL_ID_ELEM_CONTENT_7 54
+#define ED_CTRL_ID_AMOEBA_CONTENT 55
+
+/* text input identifiers */
+#define ED_CTRL_ID_LEVEL_NAME 56
+#define ED_CTRL_ID_LEVEL_AUTHOR 57
+
+/* gadgets for scrolling of drawing area */
+#define ED_CTRL_ID_SCROLL_UP 58
+#define ED_CTRL_ID_SCROLL_DOWN 59
+#define ED_CTRL_ID_SCROLL_LEFT 60
+#define ED_CTRL_ID_SCROLL_RIGHT 61
+#define ED_CTRL_ID_SCROLL_VERTICAL 62
+#define ED_CTRL_ID_SCROLL_HORIZONTAL 63
+
+#define ED_NUM_GADGETS 64
+
+/* values for counter gadgets */
+#define ED_COUNTER_ID_ELEM_SCORE 0
+#define ED_COUNTER_ID_ELEM_CONTENT 1
+#define ED_COUNTER_ID_LEVEL_XSIZE 2
+#define ED_COUNTER_ID_LEVEL_YSIZE 3
+#define ED_COUNTER_ID_LEVEL_RANDOM 4
+#define ED_COUNTER_ID_LEVEL_COLLECT 5
+#define ED_COUNTER_ID_LEVEL_TIMELIMIT 6
+#define ED_COUNTER_ID_LEVEL_TIMESCORE 7
+
+/* values for text input gadgets */
+#define ED_TEXTINPUT_ID_LEVEL_NAME 0
+#define ED_TEXTINPUT_ID_LEVEL_AUTHOR 1
+
+#define ED_NUM_COUNTERBUTTONS 8
+#define ED_NUM_SCROLLBUTTONS 4
+#define ED_NUM_SCROLLBARS 2
+#define ED_NUM_TEXTINPUT 2
+
+/* values for CopyLevelToUndoBuffer() */
+#define UNDO_IMMEDIATE 0
+#define UNDO_ACCUMULATE 1
+
+/* values for ClearEditorGadgetInfoText() and HandleGadgetInfoText() */
+#define INFOTEXT_XPOS SX
+#define INFOTEXT_YPOS (SY + SYSIZE - MINI_TILEX + 2)
+#define INFOTEXT_XSIZE SXSIZE
+#define INFOTEXT_YSIZE MINI_TILEX
+#define MAX_INFOTEXT_LEN (SXSIZE / FONT2_XSIZE)
+
+static struct
+{
+ char shortcut;
+ char *text;
+} control_info[ED_NUM_CTRL_BUTTONS] =
+{
+ { 's', "draw single items" },
+ { 'd', "draw connected items" },
+ { 'l', "draw lines" },
+ { 't', "enter text elements" },
+ { 'r', "draw outline rectangles" },
+ { 'R', "draw filled rectangles" },
+ { '\0', "wrap (rotate) level up" },
+ { '?', "properties of drawing element" },
+ { 'f', "flood fill" },
+ { '\0', "wrap (rotate) level left" },
+ { '\0', "" },
+ { '\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', "level properties" },
+ { 'S', "save level" },
+ { 'C', "clear level" },
+ { 'T', "test level" },
+ { 'E', "exit level editor" }
+};
+
+/* pointers to counter values */
+static int *gadget_elem_score_value = NULL;
+static int *gadget_elem_content_value = NULL;
+static int *gadget_level_xsize_value = NULL;
+static int *gadget_level_ysize_value = NULL;
+static int *gadget_level_random_value = NULL;
+static int *gadget_level_collect_value = NULL;
+static int *gadget_level_timelimit_value = NULL;
+static int *gadget_level_timescore_value = NULL;
+
+static struct
+{
+ int x, y;
+ int min_value, max_value;
+ int gadget_id_down, gadget_id_up;
+ int gadget_id_text;
+ int **counter_value;
+ char *infotext;
+} counterbutton_info[ED_NUM_COUNTERBUTTONS] =
+{
+ {
+ ED_COUNT_ELEM_SCORE_XPOS, ED_COUNT_ELEM_SCORE_YPOS,
+ MIN_SCORE, MAX_SCORE,
+ ED_CTRL_ID_ELEM_SCORE_DOWN, ED_CTRL_ID_ELEM_SCORE_UP,
+ ED_CTRL_ID_ELEM_SCORE_TEXT,
+ &gadget_elem_score_value,
+ "element score"
+ },
+ {
+ ED_COUNT_ELEM_CONTENT_XPOS, ED_COUNT_ELEM_CONTENT_YPOS,
+ MIN_ELEM_CONTENT, MAX_ELEM_CONTENT,
+ ED_CTRL_ID_ELEM_CONTENT_DOWN, ED_CTRL_ID_ELEM_CONTENT_UP,
+ ED_CTRL_ID_ELEM_CONTENT_TEXT,
+ &gadget_elem_content_value,
+ "element content"
+ },
+ {
+ ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(0),
+ MIN_LEV_FIELDX, MAX_LEV_FIELDX,
+ ED_CTRL_ID_LEVEL_XSIZE_DOWN, ED_CTRL_ID_LEVEL_XSIZE_UP,
+ ED_CTRL_ID_LEVEL_XSIZE_TEXT,
+ &gadget_level_xsize_value,
+ "playfield width"
+ },
+ {
+ ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(1),
+ MIN_LEV_FIELDY, MAX_LEV_FIELDY,
+ ED_CTRL_ID_LEVEL_YSIZE_DOWN, ED_CTRL_ID_LEVEL_YSIZE_UP,
+ ED_CTRL_ID_LEVEL_YSIZE_TEXT,
+ &gadget_level_ysize_value,
+ "playfield height"
+ },
+ {
+ ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(2),
+ 0, 100,
+ ED_CTRL_ID_LEVEL_RANDOM_DOWN, ED_CTRL_ID_LEVEL_RANDOM_UP,
+ ED_CTRL_ID_LEVEL_RANDOM_TEXT,
+ &gadget_level_random_value,
+ "number of random elements"
+ },
+ {
+ ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(3),
+ 0, 999,
+ ED_CTRL_ID_LEVEL_COLLECT_DOWN, ED_CTRL_ID_LEVEL_COLLECT_UP,
+ ED_CTRL_ID_LEVEL_COLLECT_TEXT,
+ &gadget_level_collect_value,
+ "number of emeralds to collect"
+ },
+ {
+ ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(4),
+ 0, 999,
+ ED_CTRL_ID_LEVEL_TIMELIMIT_DOWN, ED_CTRL_ID_LEVEL_TIMELIMIT_UP,
+ ED_CTRL_ID_LEVEL_TIMELIMIT_TEXT,
+ &gadget_level_timelimit_value,
+ "time available to solve level"
+ },
+ {
+ ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(5),
+ 0, 255,
+ ED_CTRL_ID_LEVEL_TIMESCORE_DOWN, ED_CTRL_ID_LEVEL_TIMESCORE_UP,
+ ED_CTRL_ID_LEVEL_TIMESCORE_TEXT,
+ &gadget_level_timescore_value,
+ "score for each 10 seconds left"
+ },
+};
+
+static struct
+{
+ int x, y;
+ int gadget_id;
+ char *value;
+ char *infotext;
+} textinput_info[ED_NUM_TEXTINPUT] =
+{
+ {
+ ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(6),
+ ED_CTRL_ID_LEVEL_NAME,
+ level.name,
+ "Level Title"
+ },
+ {
+ ED_LEVELINFO_XPOS, ED_COUNTER_YPOS(7),
+ ED_CTRL_ID_LEVEL_AUTHOR,
+ level.author,
+ "Level Author"
+ }
+};
+
+static struct
+{
+ int xpos, ypos;
+ int x, y;
+ int gadget_id;
+ char *infotext;
+} scrollbutton_info[ED_NUM_SCROLLBUTTONS] =
+{
+ {
+ ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 0 * ED_SCROLLBUTTON_YSIZE,
+ ED_SCROLL_UP_XPOS, ED_SCROLL_UP_YPOS, ED_CTRL_ID_SCROLL_UP,
+ "scroll level editing area up"
+ },
+ {
+ ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 1 * ED_SCROLLBUTTON_YSIZE,
+ ED_SCROLL_DOWN_XPOS, ED_SCROLL_DOWN_YPOS, ED_CTRL_ID_SCROLL_DOWN,
+ "scroll level editing area down"
+ },
+ {
+ ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 2 * ED_SCROLLBUTTON_YSIZE,
+ ED_SCROLL_LEFT_XPOS, ED_SCROLL_LEFT_YPOS, ED_CTRL_ID_SCROLL_LEFT,
+ "scroll level editing area left"
+ },
+ {
+ ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 3 * ED_SCROLLBUTTON_YSIZE,
+ ED_SCROLL_RIGHT_XPOS, ED_SCROLL_RIGHT_YPOS, ED_CTRL_ID_SCROLL_RIGHT,
+ "scroll level editing area right"
+ }
+};
+
+static struct
+{
+ int xpos, ypos;
+ int x, y;
+ int width, height;
+ int type;
+ int gadget_id;
+ char *text;
+} scrollbar_info[ED_NUM_SCROLLBARS] =
+{
+ {
+ ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS,
+ ED_SCROLL_VERTICAL_XPOS, ED_SCROLL_VERTICAL_YPOS,
+ ED_SCROLL_VERTICAL_XSIZE, ED_SCROLL_VERTICAL_YSIZE,
+ GD_TYPE_SCROLLBAR_VERTICAL,
+ ED_CTRL_ID_SCROLL_VERTICAL,
+ "scroll level editing area vertically"
+ },
+ {
+ ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS,
+ ED_SCROLL_HORIZONTAL_XPOS, ED_SCROLL_HORIZONTAL_YPOS,
+ ED_SCROLL_HORIZONTAL_XSIZE, ED_SCROLL_HORIZONTAL_YSIZE,
+ GD_TYPE_SCROLLBAR_HORIZONTAL,
+ ED_CTRL_ID_SCROLL_HORIZONTAL,
+ "scroll level editing area horizontally"
+ },
+};
+
+/* forward declaration for internal use */
+static void DrawDrawingWindow();
+static void DrawLevelInfoWindow();
+static void DrawPropertiesWindow();
+static void CopyLevelToUndoBuffer(int);
+static void HandleControlButtons(struct GadgetInfo *);
+static void HandleCounterButtons(struct GadgetInfo *);
+static void HandleDrawingAreas(struct GadgetInfo *);
+static void HandleDrawingAreaInfo(struct GadgetInfo *);
+static void HandleTextInputGadgets(struct GadgetInfo *);
+
+static struct GadgetInfo *level_editor_gadget[ED_NUM_GADGETS];
+static boolean level_editor_gadgets_created = FALSE;
+
+static int drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
+static int last_drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
+static boolean draw_with_brush = FALSE;
+static int properties_element = 0;
+
+static short ElementContent[MAX_ELEM_CONTENT][3][3];
+static short FieldBackup[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+static short UndoBuffer[NUM_UNDO_STEPS][MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+static int undo_buffer_position = 0;
+static int undo_buffer_steps = 0;
+
+static int random_placement_percentage = 10;
+static int random_placement_num_objects = 10;
+#if 0
+static int random_placement_method = RANDOM_USE_PERCENTAGE;
+#else
+static int random_placement_method = RANDOM_USE_NUM_OBJECTS;
+#endif