1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * (c) 1995-98 Artsoft Entertainment *
8 * phone: ++49 +521 290471 *
9 * email: aeglos@valinor.owl.de *
10 *----------------------------------------------------------*
12 ***********************************************************/
23 /* positions in the level editor */
24 #define ED_WIN_MB_LEFT_XPOS 7
25 #define ED_WIN_MB_LEFT_YPOS 6
26 #define ED_WIN_LEVELNR_XPOS 77
27 #define ED_WIN_LEVELNR_YPOS 7
28 #define ED_WIN_MB_MIDDLE_XPOS 7
29 #define ED_WIN_MB_MIDDLE_YPOS 258
30 #define ED_WIN_MB_RIGHT_XPOS 77
31 #define ED_WIN_MB_RIGHT_YPOS 258
33 /* other constants for the editor */
34 #define ED_SCROLL_NO 0
35 #define ED_SCROLL_LEFT 1
36 #define ED_SCROLL_RIGHT 2
37 #define ED_SCROLL_UP 4
38 #define ED_SCROLL_DOWN 8
40 /* screens in the level editor */
41 #define ED_MODE_DRAWING 0
42 #define ED_MODE_INFO 1
43 #define ED_MODE_PROPERTIES 2
45 /* how many steps can be cancelled */
46 #define NUM_UNDO_STEPS (10 + 1)
48 /* values for random placement */
49 #define RANDOM_USE_PERCENTAGE 0
50 #define RANDOM_USE_NUM_OBJECTS 1
52 /* values for elements with content */
53 #define MAX_ELEMCONT 8
55 /* values for the control window */
56 #define ED_CTRL_BUTTONS_GFX_YPOS 236
57 #define ED_CTRL_BUTTONS_ALT_GFX_YPOS 142
59 #define ED_CTRL1_BUTTONS_HORIZ 4
60 #define ED_CTRL1_BUTTONS_VERT 4
61 #define ED_CTRL1_BUTTON_XSIZE 22
62 #define ED_CTRL1_BUTTON_YSIZE 22
63 #define ED_CTRL1_BUTTONS_XPOS 6
64 #define ED_CTRL1_BUTTONS_YPOS 6
65 #define ED_CTRL2_BUTTONS_HORIZ 3
66 #define ED_CTRL2_BUTTONS_VERT 2
67 #define ED_CTRL2_BUTTON_XSIZE 30
68 #define ED_CTRL2_BUTTON_YSIZE 20
69 #define ED_CTRL2_BUTTONS_XPOS 5
70 #define ED_CTRL2_BUTTONS_YPOS 100
71 #define ED_NUM_CTRL1_BUTTONS (ED_CTRL1_BUTTONS_HORIZ * ED_CTRL1_BUTTONS_VERT)
72 #define ED_NUM_CTRL2_BUTTONS (ED_CTRL2_BUTTONS_HORIZ * ED_CTRL2_BUTTONS_VERT)
73 #define ED_NUM_CTRL_BUTTONS (ED_NUM_CTRL1_BUTTONS + ED_NUM_CTRL2_BUTTONS)
75 /* values for properties window */
76 #define ED_PROPERTIES_XPOS (TILEX - MINI_TILEX/2)
78 /* values for counter gadgets */
79 #define ED_COUNT_VALUE_XOFFSET 5
80 #define ED_COUNT_VALUE_YOFFSET 3
81 #define ED_COUNT_SCORE_XPOS ED_PROPERTIES_XPOS
82 #define ED_COUNT_SCORE_YPOS (14 * MINI_TILEY)
83 #define ED_COUNT_ELEMCONT_XPOS ED_PROPERTIES_XPOS
84 #define ED_COUNT_ELEMCONT_YPOS (17 * MINI_TILEY)
86 /* values for element content drawing areas */
87 #define ED_AREA_ELEMCONT_XPOS (TILEX)
88 #define ED_AREA_ELEMCONT_YPOS (10 * TILEY)
90 /* values for scrolling gadgets */
91 #define ED_SCROLLBUTTON_XPOS 24
92 #define ED_SCROLLBUTTON_YPOS 0
93 #define ED_SCROLLBAR_XPOS 24
94 #define ED_SCROLLBAR_YPOS 64
96 #define ED_SCROLLBUTTON_XSIZE 16
97 #define ED_SCROLLBUTTON_YSIZE 16
99 #define ED_SCROLL_UP_XPOS (SXSIZE - ED_SCROLLBUTTON_XSIZE)
100 #define ED_SCROLL_UP_YPOS (0)
101 #define ED_SCROLL_DOWN_XPOS ED_SCROLL_UP_XPOS
102 #define ED_SCROLL_DOWN_YPOS (SYSIZE - 3 * ED_SCROLLBUTTON_YSIZE)
103 #define ED_SCROLL_LEFT_XPOS (0)
104 #define ED_SCROLL_LEFT_YPOS (SYSIZE - 2 * ED_SCROLLBUTTON_YSIZE)
105 #define ED_SCROLL_RIGHT_XPOS (SXSIZE - 2 * ED_SCROLLBUTTON_XSIZE)
106 #define ED_SCROLL_RIGHT_YPOS ED_SCROLL_LEFT_YPOS
107 #define ED_SCROLL_VERTICAL_XPOS ED_SCROLL_UP_XPOS
108 #define ED_SCROLL_VERTICAL_YPOS (ED_SCROLL_UP_YPOS + ED_SCROLLBUTTON_YSIZE)
109 #define ED_SCROLL_VERTICAL_XSIZE ED_SCROLLBUTTON_XSIZE
110 #define ED_SCROLL_VERTICAL_YSIZE (SYSIZE - 4 * ED_SCROLLBUTTON_YSIZE)
111 #define ED_SCROLL_HORIZONTAL_XPOS (ED_SCROLL_LEFT_XPOS + ED_SCROLLBUTTON_XSIZE)
112 #define ED_SCROLL_HORIZONTAL_YPOS ED_SCROLL_LEFT_YPOS
113 #define ED_SCROLL_HORIZONTAL_XSIZE (SXSIZE - 3 * ED_SCROLLBUTTON_XSIZE)
114 #define ED_SCROLL_HORIZONTAL_YSIZE ED_SCROLLBUTTON_YSIZE
116 /* control button identifiers */
117 #define ED_CTRL_ID_NONE -1
119 #define ED_CTRL_ID_SINGLE_ITEMS 0
120 #define ED_CTRL_ID_CONNECTED_ITEMS 1
121 #define ED_CTRL_ID_LINE 2
122 #define ED_CTRL_ID_TEXT 3
123 #define ED_CTRL_ID_RECTANGLE 4
124 #define ED_CTRL_ID_FILLED_BOX 5
125 #define ED_CTRL_ID_WRAP_UP 6
126 #define ED_CTRL_ID_PROPERTIES 7
127 #define ED_CTRL_ID_FLOOD_FILL 8
128 #define ED_CTRL_ID_WRAP_LEFT 9
129 #define ED_CTRL_ID_UNUSED1 10
130 #define ED_CTRL_ID_WRAP_RIGHT 11
131 #define ED_CTRL_ID_RANDOM_PLACEMENT 12
132 #define ED_CTRL_ID_GRAB_BRUSH 13
133 #define ED_CTRL_ID_WRAP_DOWN 14
134 #define ED_CTRL_ID_PICK_ELEMENT 15
135 #define ED_CTRL_ID_UNDO 16
136 #define ED_CTRL_ID_INFO 17
137 #define ED_CTRL_ID_SAVE 18
138 #define ED_CTRL_ID_CLEAR 19
139 #define ED_CTRL_ID_TEST 20
140 #define ED_CTRL_ID_EXIT 21
142 /* counter button identifiers */
143 #define ED_CTRL_ID_SCORE_DOWN 22
144 #define ED_CTRL_ID_SCORE_UP 23
145 #define ED_CTRL_ID_ELEMCONT_DOWN 24
146 #define ED_CTRL_ID_ELEMCONT_UP 25
148 /* drawing area identifiers */
149 #define ED_CTRL_ID_DRAWING_LEVEL 26
150 #define ED_CTRL_ID_ELEMCONT_0 27
151 #define ED_CTRL_ID_ELEMCONT_7 34
152 #define ED_CTRL_ID_AMOEBA_CONTENT 35
154 /* text input identifiers */
155 #define ED_CTRL_ID_LEVEL_NAME 36
157 /* gadgets for scrolling of drawing area */
158 #define ED_CTRL_ID_SCROLL_UP 37
159 #define ED_CTRL_ID_SCROLL_DOWN 38
160 #define ED_CTRL_ID_SCROLL_LEFT 39
161 #define ED_CTRL_ID_SCROLL_RIGHT 40
162 #define ED_CTRL_ID_SCROLL_VERTICAL 41
163 #define ED_CTRL_ID_SCROLL_HORIZONTAL 42
165 #define ED_NUM_GADGETS 43
167 /* values for counter gadgets */
168 #define ED_COUNTER_SCORE 0
169 #define ED_COUNTER_ELEMCONT 1
171 #define ED_NUM_COUNTERBUTTONS 2
172 #define ED_NUM_SCROLLBUTTONS 4
173 #define ED_NUM_SCROLLBARS 2
175 /* values for CopyLevelToUndoBuffer() */
176 #define UNDO_IMMEDIATE 0
177 #define UNDO_ACCUMULATE 1
179 static char *control_infotext[ED_NUM_CTRL_BUTTONS] =
182 "draw connected items",
184 "enter text elements",
185 "draw outline rectangles",
187 "wrap (rotate) level up",
188 "properties of drawing element",
190 "wrap (rotate) level left",
192 "wrap (rotate) level right",
193 "random element placement",
195 "wrap (rotate) level down",
196 "pick drawing element from editing area",
197 "undo last operation",
209 } counterbutton_info[ED_NUM_COUNTERBUTTONS] =
211 { ED_COUNT_SCORE_XPOS, ED_COUNT_SCORE_YPOS, ED_CTRL_ID_SCORE_DOWN },
212 { ED_COUNT_ELEMCONT_XPOS, ED_COUNT_ELEMCONT_YPOS, ED_CTRL_ID_ELEMCONT_DOWN }
221 } scrollbutton_info[ED_NUM_SCROLLBUTTONS] =
224 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 0 * ED_SCROLLBUTTON_YSIZE,
225 ED_SCROLL_UP_XPOS, ED_SCROLL_UP_YPOS, ED_CTRL_ID_SCROLL_UP,
226 "scroll level editing area up"
229 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 1 * ED_SCROLLBUTTON_YSIZE,
230 ED_SCROLL_DOWN_XPOS, ED_SCROLL_DOWN_YPOS, ED_CTRL_ID_SCROLL_DOWN,
231 "scroll level editing area down"
234 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 2 * ED_SCROLLBUTTON_YSIZE,
235 ED_SCROLL_LEFT_XPOS, ED_SCROLL_LEFT_YPOS, ED_CTRL_ID_SCROLL_LEFT,
236 "scroll level editing area left"
239 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 3 * ED_SCROLLBUTTON_YSIZE,
240 ED_SCROLL_RIGHT_XPOS, ED_SCROLL_RIGHT_YPOS, ED_CTRL_ID_SCROLL_RIGHT,
241 "scroll level editing area right"
253 } scrollbar_info[ED_NUM_SCROLLBARS] =
256 ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS,
257 ED_SCROLL_VERTICAL_XPOS, ED_SCROLL_VERTICAL_YPOS,
258 ED_SCROLL_VERTICAL_XSIZE, ED_SCROLL_VERTICAL_YSIZE,
259 GD_TYPE_SCROLLBAR_VERTICAL,
260 ED_CTRL_ID_SCROLL_VERTICAL,
261 "scroll level editing area vertically"
264 ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS,
265 ED_SCROLL_HORIZONTAL_XPOS, ED_SCROLL_HORIZONTAL_YPOS,
266 ED_SCROLL_HORIZONTAL_XSIZE, ED_SCROLL_HORIZONTAL_YSIZE,
267 GD_TYPE_SCROLLBAR_HORIZONTAL,
268 ED_CTRL_ID_SCROLL_HORIZONTAL,
269 "scroll level editing area horizontally"
273 /* forward declaration for internal use */
274 static void DrawDrawingWindow();
275 static void DrawPropertiesWindow();
276 static void CopyLevelToUndoBuffer(int);
277 static void HandleControlButtons(struct GadgetInfo *);
278 static void HandleCounterButtons(struct GadgetInfo *);
279 static void HandleDrawingAreas(struct GadgetInfo *);
280 static void HandleDrawingAreaInfo(struct GadgetInfo *);
281 static void HandleTextInputGadgets(struct GadgetInfo *);
283 static struct GadgetInfo *level_editor_gadget[ED_NUM_GADGETS];
284 static boolean level_editor_gadgets_created = FALSE;
286 static int drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
287 static int last_drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
288 static boolean draw_with_brush = FALSE;
289 static int properties_element = 0;
291 static short ElementContent[MAX_ELEMCONT][3][3];
292 static short FieldBackup[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
293 static short UndoBuffer[NUM_UNDO_STEPS][MAX_LEV_FIELDX][MAX_LEV_FIELDY];
294 static int undo_buffer_position = 0;
295 static int undo_buffer_steps = 0;
297 static int random_placement_percentage = 10;
298 static int random_placement_num_objects = 10;
300 static int random_placement_method = RANDOM_USE_PERCENTAGE;
302 static int random_placement_method = RANDOM_USE_NUM_OBJECTS;
305 /* pointer to score value */
306 static int *gadget_score_value;
307 static int *gadget_areas_value;
309 static int level_xpos,level_ypos;
310 static int edit_mode;
311 static boolean name_typing;
312 static int new_element1 = EL_MAUERWERK;
313 static int new_element2 = EL_LEERRAUM;
314 static int new_element3 = EL_ERDREICH;
316 int element_shift = 0;
318 int editor_element[] =
320 EL_CHAR_A + ('B' - 'A'),
321 EL_CHAR_A + ('O' - 'A'),
322 EL_CHAR_A + ('U' - 'A'),
323 EL_CHAR_A + ('L' - 'A'),
326 EL_CHAR_A + ('D' - 'A'),
327 EL_CHAR_A + ('E' - 'A'),
328 EL_CHAR_A + ('R' - 'A'),
330 EL_CHAR_A + ('D' - 'A'),
331 EL_CHAR_A + ('A' - 'A'),
332 EL_CHAR_A + ('S' - 'A'),
333 EL_CHAR_A + ('H' - 'A'),
360 EL_CHAR_A + ('E' - 'A'),
361 EL_CHAR_A + ('M' - 'A'),
362 EL_CHAR_A + ('E' - 'A'),
365 EL_CHAR_A + ('R' - 'A'),
366 EL_CHAR_A + ('A' - 'A'),
367 EL_CHAR_A + ('L' - 'A'),
368 EL_CHAR_A + ('D' - 'A'),
370 EL_CHAR_A + ('M' - 'A'),
371 EL_CHAR_A + ('I' - 'A'),
372 EL_CHAR_A + ('N' - 'A'),
373 EL_CHAR_A + ('E' - 'A'),
450 EL_CHAR_A + ('M' - 'A'),
451 EL_CHAR_A + ('O' - 'A'),
452 EL_CHAR_A + ('R' - 'A'),
453 EL_CHAR_A + ('E' - 'A'),
505 EL_CHAR_A + ('S' - 'A'),
506 EL_CHAR_A + ('O' - 'A'),
507 EL_CHAR_A + ('K' - 'A'),
508 EL_CHAR_A + ('O' - 'A'),
511 EL_CHAR_A + ('B' - 'A'),
512 EL_CHAR_A + ('A' - 'A'),
513 EL_CHAR_A + ('N' - 'A'),
516 EL_SOKOBAN_FELD_LEER,
517 EL_SOKOBAN_FELD_VOLL,
586 EL_CHAR_A + ('D' - 'A'),
587 EL_CHAR_A + ('Y' - 'A'),
588 EL_CHAR_A + ('N' - 'A'),
589 EL_CHAR_A + ('A' - 'A'),
591 EL_CHAR_A + ('B' - 'A'),
592 EL_CHAR_A + ('L' - 'A'),
593 EL_CHAR_A + ('A' - 'A'),
594 EL_CHAR_A + ('S' - 'A'),
597 EL_CHAR_A + ('T' - 'A'),
598 EL_CHAR_A + ('E' - 'A'),
599 EL_CHAR_A + ('R' - 'A'),
682 int elements_in_list = sizeof(editor_element)/sizeof(int);
684 static void ScrollMiniLevel(int from_x, int from_y, int scroll)
687 int dx = (scroll == ED_SCROLL_LEFT ? -1 : scroll == ED_SCROLL_RIGHT ? 1 : 0);
688 int dy = (scroll == ED_SCROLL_UP ? -1 : scroll == ED_SCROLL_DOWN ? 1 : 0);
690 XCopyArea(display, drawto, drawto, gc,
691 SX + (dx == -1 ? MINI_TILEX : 0),
692 SY + (dy == -1 ? MINI_TILEY : 0),
693 (ED_FIELDX * MINI_TILEX) - (dx != 0 ? MINI_TILEX : 0),
694 (ED_FIELDY * MINI_TILEY) - (dy != 0 ? MINI_TILEY : 0),
695 SX + (dx == +1 ? MINI_TILEX : 0),
696 SY + (dy == +1 ? MINI_TILEY : 0));
699 x = (dx == 1 ? 0 : ED_FIELDX - 1);
700 for(y=0; y<ED_FIELDY; y++)
701 DrawMiniElementOrWall(x, y, from_x, from_y);
705 y = (dy == 1 ? 0 : ED_FIELDY - 1);
706 for(x=0; x<ED_FIELDX; x++)
707 DrawMiniElementOrWall(x, y, from_x, from_y);
710 redraw_mask |= REDRAW_FIELD;
714 void InitLevelEditorGadgets()
718 for (i=0; i<ED_NUM_GADGETS; i++)
719 level_editor_gadget[i] = NULL;
722 static void CreateControlButtons()
724 Pixmap gd_pixmap = pix[PIX_DOOR];
725 struct GadgetInfo *gi;
726 unsigned long event_mask;
729 /* create toolbox buttons */
730 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
734 int gd_xoffset, gd_yoffset;
735 int gd_x1, gd_x2, gd_y1, gd_y2;
738 boolean radio_button_pressed;
740 if (id == ED_CTRL_ID_SINGLE_ITEMS ||
741 id == ED_CTRL_ID_CONNECTED_ITEMS ||
742 id == ED_CTRL_ID_LINE ||
743 id == ED_CTRL_ID_TEXT ||
744 id == ED_CTRL_ID_RECTANGLE ||
745 id == ED_CTRL_ID_FILLED_BOX ||
746 id == ED_CTRL_ID_FLOOD_FILL ||
747 id == ED_CTRL_ID_GRAB_BRUSH ||
748 id == ED_CTRL_ID_PICK_ELEMENT)
750 button_type = GD_TYPE_RADIO_BUTTON;
752 radio_button_pressed = (id == drawing_function ? TRUE : FALSE);
753 event_mask = GD_EVENT_PRESSED;
757 button_type = GD_TYPE_NORMAL_BUTTON;
759 radio_button_pressed = FALSE;
761 if (id == ED_CTRL_ID_WRAP_LEFT ||
762 id == ED_CTRL_ID_WRAP_RIGHT ||
763 id == ED_CTRL_ID_WRAP_UP ||
764 id == ED_CTRL_ID_WRAP_DOWN)
765 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
767 event_mask = GD_EVENT_RELEASED;
770 if (id < ED_NUM_CTRL1_BUTTONS)
772 int x = i % ED_CTRL1_BUTTONS_HORIZ;
773 int y = i / ED_CTRL1_BUTTONS_HORIZ;
775 gd_xoffset = ED_CTRL1_BUTTONS_XPOS + x * ED_CTRL1_BUTTON_XSIZE;
776 gd_yoffset = ED_CTRL1_BUTTONS_YPOS + y * ED_CTRL1_BUTTON_YSIZE;
777 width = ED_CTRL1_BUTTON_XSIZE;
778 height = ED_CTRL1_BUTTON_YSIZE;
782 int x = (i - ED_NUM_CTRL1_BUTTONS) % ED_CTRL2_BUTTONS_HORIZ;
783 int y = (i - ED_NUM_CTRL1_BUTTONS) / ED_CTRL2_BUTTONS_HORIZ;
785 gd_xoffset = ED_CTRL2_BUTTONS_XPOS + x * ED_CTRL2_BUTTON_XSIZE;
786 gd_yoffset = ED_CTRL2_BUTTONS_YPOS + y * ED_CTRL2_BUTTON_YSIZE;
787 width = ED_CTRL2_BUTTON_XSIZE;
788 height = ED_CTRL2_BUTTON_YSIZE;
791 gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
792 gd_x2 = DOOR_GFX_PAGEX7 + gd_xoffset;
793 gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_GFX_YPOS + gd_yoffset;
794 gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
796 gi = CreateGadget(GDI_CUSTOM_ID, id,
797 GDI_DESCRIPTION_TEXT, control_infotext[i],
798 GDI_X, EX + gd_xoffset,
799 GDI_Y, EY + gd_yoffset,
802 GDI_TYPE, button_type,
803 GDI_STATE, GD_BUTTON_UNPRESSED,
804 GDI_RADIO_NR, radio_button_nr,
805 GDI_RADIO_PRESSED, radio_button_pressed,
806 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
807 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y1,
808 GDI_ALT_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y2,
809 GDI_ALT_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
810 GDI_EVENT_MASK, event_mask,
811 GDI_CALLBACK_ACTION, HandleControlButtons,
815 Error(ERR_EXIT, "cannot create gadget");
817 level_editor_gadget[id] = gi;
820 /* create buttons for scrolling of drawing area */
821 for (i=0; i<ED_NUM_SCROLLBUTTONS; i++)
823 int id = scrollbutton_info[i].gadget_id;
824 int gd_x1, gd_x2, gd_y;
826 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
828 gd_y = DOOR_GFX_PAGEY1 + scrollbutton_info[i].ypos;
829 gd_x1 = DOOR_GFX_PAGEX8 + scrollbutton_info[i].xpos;
830 gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
832 gi = CreateGadget(GDI_CUSTOM_ID, id,
833 GDI_DESCRIPTION_TEXT, scrollbutton_info[i].text,
834 GDI_X, SX + scrollbutton_info[i].x,
835 GDI_Y, SY + scrollbutton_info[i].y,
836 GDI_WIDTH, ED_SCROLLBUTTON_XSIZE,
837 GDI_HEIGHT, ED_SCROLLBUTTON_YSIZE,
838 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
839 GDI_STATE, GD_BUTTON_UNPRESSED,
840 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
841 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
842 GDI_EVENT_MASK, event_mask,
843 GDI_CALLBACK_ACTION, HandleControlButtons,
847 Error(ERR_EXIT, "cannot create gadget");
849 level_editor_gadget[id] = gi;
853 static void CreateCounterButtons()
857 for (i=0; i<ED_NUM_COUNTERBUTTONS; i++)
861 Pixmap gd_pixmap = pix[PIX_DOOR];
862 struct GadgetInfo *gi;
863 int id = counterbutton_info[i].gadget_id + j;
865 int gd_x1, gd_x2, gd_y;
866 unsigned long event_mask;
868 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
870 gd_xoffset = (j == 0 ? ED_BUTTON_MINUS_XPOS : ED_BUTTON_PLUS_XPOS);
871 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
872 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
873 gd_y = DOOR_GFX_PAGEY1 + ED_BUTTON_COUNT_YPOS;
875 gi = CreateGadget(GDI_CUSTOM_ID, id,
876 GDI_X, SX + counterbutton_info[i].x + gd_xoffset,
877 GDI_Y, SY + counterbutton_info[i].y,
878 GDI_WIDTH, ED_BUTTON_COUNT_XSIZE,
879 GDI_HEIGHT, ED_BUTTON_COUNT_YSIZE,
880 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
881 GDI_STATE, GD_BUTTON_UNPRESSED,
882 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
883 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
884 GDI_EVENT_MASK, event_mask,
885 GDI_CALLBACK_ACTION, HandleCounterButtons,
889 Error(ERR_EXIT, "cannot create gadget");
891 level_editor_gadget[id] = gi;
896 static void CreateDrawingAreas()
898 struct GadgetInfo *gi;
899 unsigned long event_mask;
904 GD_EVENT_PRESSED | GD_EVENT_RELEASED | GD_EVENT_MOVING |
905 GD_EVENT_OFF_BORDERS;
907 /* one for the level drawing area ... */
908 id = ED_CTRL_ID_DRAWING_LEVEL;
909 gi = CreateGadget(GDI_CUSTOM_ID, id,
912 GDI_TYPE, GD_TYPE_DRAWING_AREA,
913 GDI_AREA_SIZE, ED_FIELDX, ED_FIELDY,
914 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
915 GDI_EVENT_MASK, event_mask,
916 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
917 GDI_CALLBACK_ACTION, HandleDrawingAreas,
921 Error(ERR_EXIT, "cannot create gadget");
923 level_editor_gadget[id] = gi;
925 /* ... up to eight areas for element content ... */
926 for (i=0; i<MAX_ELEMCONT; i++)
928 int gx = SX + ED_AREA_ELEMCONT_XPOS + 5 * (i % 4) * MINI_TILEX;
929 int gy = SX + ED_AREA_ELEMCONT_YPOS + 6 * (i / 4) * MINI_TILEY;
931 id = ED_CTRL_ID_ELEMCONT_0 + i;
932 gi = CreateGadget(GDI_CUSTOM_ID, id,
935 GDI_WIDTH, 3 * MINI_TILEX,
936 GDI_HEIGHT, 3 * MINI_TILEY,
937 GDI_TYPE, GD_TYPE_DRAWING_AREA,
938 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
939 GDI_EVENT_MASK, event_mask,
940 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
941 GDI_CALLBACK_ACTION, HandleDrawingAreas,
945 Error(ERR_EXIT, "cannot create gadget");
947 level_editor_gadget[id] = gi;
950 /* ... and one for the amoeba content */
951 id = ED_CTRL_ID_AMOEBA_CONTENT;
952 gi = CreateGadget(GDI_CUSTOM_ID, id,
953 GDI_X, SX + ED_AREA_ELEMCONT_XPOS,
954 GDI_Y, SY + ED_AREA_ELEMCONT_YPOS,
955 GDI_WIDTH, MINI_TILEX,
956 GDI_HEIGHT, MINI_TILEY,
957 GDI_TYPE, GD_TYPE_DRAWING_AREA,
958 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
959 GDI_EVENT_MASK, event_mask,
960 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
961 GDI_CALLBACK_ACTION, HandleDrawingAreas,
965 Error(ERR_EXIT, "cannot create gadget");
967 level_editor_gadget[id] = gi;
970 static void CreateTextInputGadgets()
972 Pixmap gd_pixmap = pix[PIX_DOOR];
974 struct GadgetInfo *gi;
975 unsigned long event_mask;
978 gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
979 gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
980 event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
982 /* text input gadget for the level name */
983 id = ED_CTRL_ID_LEVEL_NAME;
984 gi = CreateGadget(GDI_CUSTOM_ID, id,
985 GDI_X, SX + ED_COUNT_ELEMCONT_XPOS,
986 GDI_Y, SY + ED_AREA_ELEMCONT_YPOS + 3 * TILEX,
987 GDI_TYPE, GD_TYPE_TEXTINPUT,
988 GDI_TEXT_VALUE, level.name,
990 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y,
991 GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y,
992 GDI_DESIGN_BORDER, 3,
993 GDI_EVENT_MASK, event_mask,
994 GDI_CALLBACK_ACTION, HandleTextInputGadgets,
998 Error(ERR_EXIT, "cannot create gadget");
1000 level_editor_gadget[id] = gi;
1003 static void CreateScrollbarGadgets()
1007 for (i=0; i<ED_NUM_SCROLLBARS; i++)
1009 int id = scrollbar_info[i].gadget_id;
1010 Pixmap gd_pixmap = pix[PIX_DOOR];
1011 int gd_x1, gd_x2, gd_y1, gd_y2;
1012 struct GadgetInfo *gi;
1013 int items_max, items_visible, item_position;
1014 unsigned long event_mask;
1016 if (scrollbar_info[i].type == GD_TYPE_SCROLLBAR_HORIZONTAL)
1018 items_max = lev_fieldx + 2;
1019 items_visible = ED_FIELDX;
1024 items_max = lev_fieldy + 2;
1025 items_visible = ED_FIELDY;
1029 event_mask = GD_EVENT_MOVING | GD_EVENT_OFF_BORDERS;
1031 gd_x1 = DOOR_GFX_PAGEX8 + scrollbar_info[i].xpos;
1032 gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
1033 gd_y1 = DOOR_GFX_PAGEY1 + scrollbar_info[i].ypos;
1034 gd_y2 = DOOR_GFX_PAGEY1 + scrollbar_info[i].ypos;
1036 gi = CreateGadget(GDI_CUSTOM_ID, id,
1037 GDI_DESCRIPTION_TEXT, scrollbar_info[i].text,
1038 GDI_X, SX + scrollbar_info[i].x,
1039 GDI_Y, SY + scrollbar_info[i].y,
1040 GDI_WIDTH, scrollbar_info[i].width,
1041 GDI_HEIGHT, scrollbar_info[i].height,
1042 GDI_TYPE, scrollbar_info[i].type,
1043 GDI_SCROLLBAR_ITEMS_MAX, items_max,
1044 GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
1045 GDI_SCROLLBAR_ITEM_POSITION, item_position,
1046 GDI_STATE, GD_BUTTON_UNPRESSED,
1047 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
1048 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
1049 GDI_DESIGN_BORDER, 3,
1050 GDI_EVENT_MASK, event_mask,
1051 GDI_CALLBACK_ACTION, HandleControlButtons,
1055 Error(ERR_EXIT, "cannot create gadget");
1057 level_editor_gadget[id] = gi;
1061 static void CreateLevelEditorGadgets()
1063 if (level_editor_gadgets_created)
1066 CreateControlButtons();
1067 CreateCounterButtons();
1068 CreateDrawingAreas();
1069 CreateTextInputGadgets();
1070 CreateScrollbarGadgets();
1072 level_editor_gadgets_created = TRUE;
1075 static void MapControlButtons()
1079 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
1080 MapGadget(level_editor_gadget[i]);
1083 static void MapCounterButtons(int id)
1088 MapGadget(level_editor_gadget[counterbutton_info[id].gadget_id + i]);
1091 static void MapDrawingArea(int id)
1093 MapGadget(level_editor_gadget[id]);
1096 static void MapTextInputGadget(int id)
1098 MapGadget(level_editor_gadget[id]);
1101 static void MapMainDrawingArea()
1105 for (i=0; i<ED_NUM_SCROLLBUTTONS; i++)
1106 MapGadget(level_editor_gadget[scrollbutton_info[i].gadget_id]);
1108 for (i=0; i<ED_NUM_SCROLLBARS; i++)
1109 MapGadget(level_editor_gadget[scrollbar_info[i].gadget_id]);
1111 MapDrawingArea(ED_CTRL_ID_DRAWING_LEVEL);
1114 static void UnmapDrawingArea(int id)
1116 UnmapGadget(level_editor_gadget[id]);
1119 void UnmapLevelEditorWindowGadgets()
1123 for (i=ED_NUM_CTRL_BUTTONS; i<ED_NUM_GADGETS; i++)
1124 UnmapGadget(level_editor_gadget[i]);
1127 void UnmapLevelEditorGadgets()
1131 for (i=0; i<ED_NUM_GADGETS; i++)
1132 UnmapGadget(level_editor_gadget[i]);
1137 int i, x, y, graphic;
1141 edit_mode = ED_MODE_DRAWING;
1142 name_typing = FALSE;
1144 CloseDoor(DOOR_CLOSE_ALL);
1146 OpenDoor(DOOR_OPEN_2 | DOOR_NO_DELAY);
1148 if (level_editor_test_game)
1150 for(x=0; x<lev_fieldx; x++)
1151 for(y=0; y<lev_fieldy; y++)
1152 Feld[x][y] = Ur[x][y];
1154 for(x=0; x<lev_fieldx; x++)
1155 for(y=0; y<lev_fieldy; y++)
1156 Ur[x][y] = FieldBackup[x][y];
1158 level_editor_test_game = FALSE;
1162 undo_buffer_position = -1;
1163 undo_buffer_steps = -1;
1164 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
1168 DrawMiniLevel(level_xpos, level_ypos);
1172 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1173 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY1,
1175 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1176 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1177 DOOR_GFX_PAGEX6+ED_BUTTON_ELEM_XPOS,
1178 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS,
1179 4*ED_BUTTON_ELEM_XSIZE,5*ED_BUTTON_ELEM_YSIZE,
1180 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS,
1181 DOOR_GFX_PAGEY1+ED_BUTTON_EUP_Y2POS);
1183 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1185 if (i < elements_in_list)
1186 graphic = el2gfx(editor_element[i + element_shift]);
1188 graphic = GFX_LEERRAUM;
1190 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1191 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS+3 +
1192 (i%MAX_ELEM_X)*ED_BUTTON_ELEM_XSIZE,
1193 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS+3 +
1194 (i/MAX_ELEM_X)*ED_BUTTON_ELEM_YSIZE,
1198 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1199 DOOR_GFX_PAGEX1+ED_WIN_MB_LEFT_XPOS,
1200 DOOR_GFX_PAGEY1+ED_WIN_MB_LEFT_YPOS,
1201 el2gfx(new_element1));
1202 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1203 DOOR_GFX_PAGEX1+ED_WIN_MB_MIDDLE_XPOS,
1204 DOOR_GFX_PAGEY1+ED_WIN_MB_MIDDLE_YPOS,
1205 el2gfx(new_element2));
1206 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1207 DOOR_GFX_PAGEX1+ED_WIN_MB_RIGHT_XPOS,
1208 DOOR_GFX_PAGEY1+ED_WIN_MB_RIGHT_YPOS,
1209 el2gfx(new_element3));
1210 DrawTextExt(pix[PIX_DB_DOOR],gc,
1211 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS,
1212 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1213 int2str(level_nr,2),FS_SMALL,FC_SPECIAL1);
1214 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1215 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+3,
1216 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1218 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS,
1219 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
1220 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1221 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+14,
1222 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1224 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS+9,
1225 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
1227 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1228 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1230 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1232 /* draw bigger door */
1233 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1238 /* draw new control window */
1239 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1240 DOOR_GFX_PAGEX8, 236,
1244 redraw_mask |= REDRAW_ALL;
1246 OpenDoor(DOOR_OPEN_1);
1248 if (!level_editor_gadgets_created)
1249 CreateLevelEditorGadgets();
1251 strcpy(level_editor_gadget[ED_CTRL_ID_LEVEL_NAME]->text.value, level.name);
1253 MapControlButtons();
1256 MapMainDrawingArea();
1259 DrawDrawingWindow();
1263 OpenDoor(DOOR_OPEN_1 | DOOR_OPEN_2);
1267 void DrawControlWindow()
1272 UnmapLevelEditorWindowGadgets();
1274 /* Inhalt der Mampfer */
1275 DrawText(ED_COUNT_GADGET_XPOS+1,SY+6,
1276 "Contents of a smashed cruncher:",FS_SMALL,FC_YELLOW);
1277 for(i=0;i<4;i++) for(y=0;y<4;y++) for(x=0;x<4;x++)
1279 DrawMiniElement(1+5*i+x,2+y,EL_ERDREICH);
1280 XFillRectangle(display,drawto,gc,
1281 SX+(1+5*i)*MINI_TILEX+MINI_TILEX/2-1,
1282 SY+(2)*MINI_TILEY+MINI_TILEY/2-1,
1283 3*MINI_TILEX+2,3*MINI_TILEY+2);
1285 XCopyArea(display,drawto,drawto,gc,
1286 SX+1*MINI_TILEX,SY+2*MINI_TILEY,
1287 4*5*MINI_TILEX,5*MINI_TILEY,
1288 SX+1*MINI_TILEX-MINI_TILEX/2,SY+2*MINI_TILEY-MINI_TILEY/2);
1291 for(y=0;y<3;y++) for(x=0;x<3;x++)
1292 DrawMiniElement(1+5*i+x,2+y,level.mampfer_inhalt[i][x][y]);
1294 DrawText(SX+MINI_TILEX+(5*i+1)*MINI_TILEX+1,
1295 SY+2*MINI_TILEY+(4)*MINI_TILEY-4,
1296 int2str(i+1,1),FS_SMALL,FC_YELLOW);
1299 /* Inhalt der Amöbe */
1300 for(y=0;y<2;y++) for(x=0;x<2;x++)
1302 DrawMiniElement(29+x,26+y,EL_ERDREICH);
1303 XFillRectangle(display,drawto,gc,
1304 SX+29*MINI_TILEX+MINI_TILEX/2-1,
1305 SY+26*MINI_TILEY+MINI_TILEY/2-1,
1306 MINI_TILEX+2,MINI_TILEY+2);
1308 XCopyArea(display,drawto,drawto,gc,
1309 SX+29*MINI_TILEX,SY+26*MINI_TILEY,
1310 3*MINI_TILEX,3*MINI_TILEY,
1311 SX+29*MINI_TILEX-MINI_TILEX/2,SY+26*MINI_TILEY-MINI_TILEY/2);
1312 DrawMiniElement(29,26,level.amoebe_inhalt);
1314 for(i=0;i<11+3+2;i++)
1316 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1317 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1318 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1319 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1320 ED_COUNT_GADGET_XPOS,
1321 ED_COUNT_GADGET_YPOS+i*ED_COUNT_GADGET_YSIZE);
1324 DrawText(ED_COUNT_VALUE_XPOS,
1325 ED_COUNT_VALUE_YPOS+i*ED_COUNT_GADGET_YSIZE,
1326 int2str(level.score[i],3),FS_SMALL,FC_YELLOW);
1328 DrawText(ED_COUNT_VALUE_XPOS,
1329 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1330 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1332 DrawText(ED_COUNT_VALUE_XPOS,
1333 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1334 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1336 DrawText(ED_COUNT_VALUE_XPOS,
1337 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1338 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1340 DrawText(ED_COUNT_VALUE_XPOS,
1341 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1342 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1344 DrawText(ED_COUNT_VALUE_XPOS,
1345 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1346 int2str(level.time,3),FS_SMALL,FC_YELLOW);
1349 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+0*ED_COUNT_TEXT_YSIZE,
1350 "Score for Emerald",FS_SMALL,FC_YELLOW);
1351 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+1*ED_COUNT_TEXT_YSIZE,
1352 "Score for Diamond",FS_SMALL,FC_YELLOW);
1353 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+2*ED_COUNT_TEXT_YSIZE,
1354 "Score for smashing a Bug",FS_SMALL,FC_YELLOW);
1355 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+3*ED_COUNT_TEXT_YSIZE,
1356 "Score for smashing a Spaceship",FS_SMALL,FC_YELLOW);
1357 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+4*ED_COUNT_TEXT_YSIZE,
1358 "Score for smashing a Cruncher",FS_SMALL,FC_YELLOW);
1359 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+5*ED_COUNT_TEXT_YSIZE,
1360 "Score for smashing an Alien",FS_SMALL,FC_YELLOW);
1361 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+6*ED_COUNT_TEXT_YSIZE,
1362 "Score for smashing a Pacman",FS_SMALL,FC_YELLOW);
1363 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+7*ED_COUNT_TEXT_YSIZE,
1364 "Score for cracking a nut",FS_SMALL,FC_YELLOW);
1365 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+8*ED_COUNT_TEXT_YSIZE,
1366 "Score for dynamite",FS_SMALL,FC_YELLOW);
1367 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+9*ED_COUNT_TEXT_YSIZE,
1368 "Score for key",FS_SMALL,FC_YELLOW);
1369 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+10*ED_COUNT_TEXT_YSIZE,
1370 "Score for each 10 seconds left",FS_SMALL,FC_YELLOW);
1371 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+11*ED_COUNT_TEXT_YSIZE,
1372 "Speed of the amoeba / Content",FS_SMALL,FC_YELLOW);
1373 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+12*ED_COUNT_TEXT_YSIZE,
1374 "Time for magic wall",FS_SMALL,FC_YELLOW);
1375 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+13*ED_COUNT_TEXT_YSIZE,
1376 "Time for wheel",FS_SMALL,FC_YELLOW);
1377 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+14*ED_COUNT_TEXT_YSIZE,
1378 "Emeralds needed in this level",FS_SMALL,FC_YELLOW);
1379 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+15*ED_COUNT_TEXT_YSIZE,
1380 "Time available for this level",FS_SMALL,FC_YELLOW);
1382 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1383 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS,
1384 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1385 ED_WIN_COUNT_XSIZE,ED_WIN_COUNT_YSIZE,
1386 ED_COUNT_GADGET_XPOS,
1387 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1389 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1390 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS+3+2*FONT2_XSIZE,
1391 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1392 ED_WIN_COUNT_XSIZE-3-2*FONT2_XSIZE,ED_WIN_COUNT_YSIZE,
1393 ED_COUNT_GADGET_XPOS+3+i*FONT2_XSIZE,
1394 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1395 DrawText(ED_COUNT_GADGET_XPOS+5,
1396 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1397 level.name,FS_SMALL,FC_YELLOW);
1398 DrawText(ED_COUNT_GADGET_XPOS+(30+3)*FONT2_XSIZE-5,
1399 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1400 "Title",FS_SMALL,FC_YELLOW);
1402 DrawText(ED_SIZE_GADGET_XPOS,ED_SIZE_GADGET_YPOS-18,
1403 "Playfield size:",FS_SMALL,FC_YELLOW);
1404 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1405 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1406 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1407 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1408 ED_SIZE_GADGET_XPOS,
1409 ED_SIZE_GADGET_YPOS+0*ED_COUNT_GADGET_YSIZE);
1410 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1411 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1412 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1413 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1414 ED_SIZE_GADGET_XPOS,
1415 ED_SIZE_GADGET_YPOS+1*ED_COUNT_GADGET_YSIZE);
1416 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+0*ED_SIZE_TEXT_YSIZE,
1417 "Width",FS_SMALL,FC_YELLOW);
1418 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+1*ED_SIZE_TEXT_YSIZE,
1419 "Height",FS_SMALL,FC_YELLOW);
1420 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1421 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1422 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1423 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1426 void AdjustLevelScrollPosition()
1428 if (level_xpos < -1)
1430 if (level_xpos > lev_fieldx - ED_FIELDX + 1)
1431 level_xpos = lev_fieldx - ED_FIELDX + 1;
1432 if (lev_fieldx < ED_FIELDX - 2)
1435 if (level_ypos < -1)
1437 if (level_ypos > lev_fieldy - ED_FIELDY + 1)
1438 level_ypos = lev_fieldy - ED_FIELDY + 1;
1439 if (lev_fieldy < ED_FIELDY - 2)
1443 void AdjustEditorScrollbar(int id)
1445 struct GadgetInfo *gi = level_editor_gadget[id];
1446 struct GadgetScrollbar *gs = &gi->scrollbar;
1447 int items_max, items_visible, item_position = gs->item_position;
1449 if (id == ED_CTRL_ID_SCROLL_HORIZONTAL)
1451 items_max = lev_fieldx + 2;
1452 items_visible = ED_FIELDX;
1456 items_max = lev_fieldy + 2;
1457 items_visible = ED_FIELDY;
1460 if (item_position > items_max - items_visible)
1461 item_position = items_max - items_visible;
1463 AdjustScrollbar(gi, items_max, item_position);
1466 static void PickDrawingElement(int button, int element)
1468 if (button < 1 || button > 3)
1473 new_element1 = element;
1474 DrawMiniGraphicExt(drawto, gc,
1475 DX + ED_WIN_MB_LEFT_XPOS,
1476 DY + ED_WIN_MB_LEFT_YPOS,
1477 el2gfx(new_element1));
1479 else if (button == 2)
1481 new_element2 = element;
1482 DrawMiniGraphicExt(drawto, gc,
1483 DX + ED_WIN_MB_MIDDLE_XPOS,
1484 DY + ED_WIN_MB_MIDDLE_YPOS,
1485 el2gfx(new_element2));
1489 new_element3 = element;
1490 DrawMiniGraphicExt(drawto, gc,
1491 DX + ED_WIN_MB_RIGHT_XPOS,
1492 DY + ED_WIN_MB_RIGHT_YPOS,
1493 el2gfx(new_element3));
1496 redraw_mask |= REDRAW_DOOR_1;
1499 void LevelEd(int mx, int my, int button)
1501 static int last_button = 0;
1502 static int in_field_pressed = FALSE;
1503 static boolean use_floodfill = FALSE;
1507 int x = (mx-SX)/MINI_TILEX;
1508 int y = (my-SY)/MINI_TILEY;
1512 HandlePressedControlButtons();
1513 HandleDrawingFunctions(mx, my, button);
1516 if (use_floodfill) /********** FLOOD FILL **********/
1524 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1529 if (x>lev_fieldx || y>lev_fieldy ||
1530 (x==0 && level_xpos<0) ||
1531 (x==ED_FIELDX-1 && level_xpos>lev_fieldx-ED_FIELDX) ||
1532 (y==0 && level_ypos<0) ||
1533 (y==ED_FIELDY-1 && level_ypos>lev_fieldy-ED_FIELDY))
1536 from_x = x+level_xpos;
1537 from_y = y+level_ypos;
1538 fill_element = (button==1 ? new_element1 :
1539 button==2 ? new_element2 :
1540 button==3 ? new_element3 : 0);
1542 FloodFill(from_x,from_y,fill_element);
1543 DrawMiniLevel(level_xpos,level_ypos);
1546 use_floodfill = FALSE;
1547 CloseDoor(DOOR_CLOSE_1);
1548 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1557 else /********** EDIT/CTRL-FENSTER **********/
1559 static unsigned long choice_delay = 0;
1560 int choice = CheckElemButtons(mx,my,button);
1561 int elem_pos = choice-ED_BUTTON_ELEM;
1563 if (((choice == ED_BUTTON_EUP && element_shift>0) ||
1564 (choice == ED_BUTTON_EDOWN &&
1565 element_shift<elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)) &&
1566 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1568 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
1572 step = (button==1 ? MAX_ELEM_X : button==2 ? 5*MAX_ELEM_X :
1574 element_shift += (choice==ED_BUTTON_EUP ? -step : step);
1576 step = step * MAX_ELEM_X * (choice == ED_BUTTON_EUP ? -1 : +1);
1577 element_shift += step;
1580 if (element_shift<0)
1582 if (element_shift>elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)
1583 element_shift = elements_in_list-MAX_ELEM_X*MAX_ELEM_Y;
1584 if (element_shift % MAX_ELEM_X)
1585 element_shift += MAX_ELEM_X-(element_shift % MAX_ELEM_X);
1587 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1588 DrawElemButton(i+2,ED_BUTTON_RELEASED);
1590 else if (elem_pos>=0 && elem_pos<MAX_ELEM_X*MAX_ELEM_Y)
1594 if (elem_pos+element_shift < elements_in_list)
1595 new_element = editor_element[elem_pos+element_shift];
1597 new_element = EL_LEERRAUM;
1599 PickDrawingElement(last_button, new_element);
1601 if (!HAS_CONTENT(properties_element))
1603 properties_element = new_element;
1604 if (edit_mode == ED_MODE_PROPERTIES)
1605 DrawPropertiesWindow();
1609 if (edit_mode == ED_MODE_DRAWING) /********** EDIT-FENSTER **********/
1616 switch(CheckEditButtons(mx,my,button))
1618 case ED_BUTTON_CTRL:
1619 CloseDoor(DOOR_CLOSE_2);
1620 DrawControlWindow();
1621 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1622 DOOR_GFX_PAGEX4,DOOR_GFX_PAGEY1+80,
1624 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1625 OpenDoor(DOOR_OPEN_2);
1626 edit_mode = ED_MODE_INFO;
1628 case ED_BUTTON_FILL:
1629 Request("Caution ! Flood fill mode ! Choose area !",REQ_OPEN);
1630 use_floodfill = TRUE;
1633 case ED_BUTTON_LEFT:
1636 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1638 if (lev_fieldx<ED_FIELDX-2)
1641 level_xpos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1645 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_RIGHT);
1647 DrawMiniLevel(level_xpos,level_ypos);
1650 case ED_BUTTON_RIGHT:
1651 if (level_xpos<=lev_fieldx-ED_FIELDX)
1653 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1655 if (lev_fieldx<ED_FIELDX-2)
1658 level_xpos += (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1659 if (level_xpos>lev_fieldx-ED_FIELDX+1)
1660 level_xpos = lev_fieldx-ED_FIELDX+1;
1662 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_LEFT);
1664 DrawMiniLevel(level_xpos,level_ypos);
1670 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1672 if (lev_fieldy<ED_FIELDY-2)
1675 level_ypos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1679 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_DOWN);
1681 DrawMiniLevel(level_xpos,level_ypos);
1684 case ED_BUTTON_DOWN:
1685 if (level_ypos<=lev_fieldy-ED_FIELDY)
1687 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1689 if (lev_fieldy<ED_FIELDY-2)
1692 level_ypos += (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1693 if (level_ypos>lev_fieldy-ED_FIELDY+1)
1694 level_ypos = lev_fieldy-ED_FIELDY+1;
1696 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_UP);
1698 DrawMiniLevel(level_xpos,level_ypos);
1711 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1715 if (button && !motion_status)
1716 in_field_pressed = TRUE;
1718 if (!button || !in_field_pressed || button<1 || button>3 ||
1719 (y==0 && level_ypos<0) ||
1720 (y==ED_FIELDY-1 && level_ypos>lev_fieldy-ED_FIELDY) ||
1721 (x==0 && level_xpos<0) ||
1722 (x==ED_FIELDX-1 && level_xpos>lev_fieldx-ED_FIELDX) ||
1723 x>lev_fieldx || y>lev_fieldy)
1726 new_element = (button==1 ? new_element1 :
1727 button==2 ? new_element2 :
1728 button==3 ? new_element3 : 0);
1730 if (new_element != Feld[x+level_xpos][y+level_ypos])
1732 if (new_element==EL_SPIELFIGUR) /* Jeder nur EINE Figur bitte... */
1736 for(x=0;x<lev_fieldx;x++) for(y=0;y<lev_fieldy;y++)
1738 if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1)
1740 Feld[x][y] = EL_LEERRAUM;
1741 if (x-level_xpos>=0 && x-level_xpos<ED_FIELDX &&
1742 y-level_ypos>=0 && y-level_ypos<ED_FIELDY)
1743 DrawMiniElement(x-level_xpos,y-level_ypos,EL_LEERRAUM);
1748 Feld[x+level_xpos][y+level_ypos] = new_element;
1749 DrawMiniElement(x,y,new_element);
1752 else if (!motion_status) /* Mauszeiger nicht im Level-Feld */
1753 in_field_pressed = FALSE;
1760 else if (edit_mode == ED_MODE_INFO)/********** KONTROLL-FENSTER **********/
1762 int choice = CheckCountButtons(mx,my,button);
1763 int step = (button==1 ? 1 : button==2 ? 5 : button==3 ? 10 : 0);
1765 if (choice >= 0 && choice < 36 &&
1766 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1775 level.score[choice] += step;
1776 if (level.score[choice]<0)
1777 level.score[choice] = 0;
1778 else if (level.score[choice]>255)
1779 level.score[choice] = 255;
1781 else if (choice==11)
1783 level.tempo_amoebe += step;
1784 if (level.tempo_amoebe<0)
1785 level.tempo_amoebe = 0;
1786 else if (level.tempo_amoebe>255)
1787 level.tempo_amoebe = 255;
1789 else if (choice==12)
1791 level.dauer_sieb += step;
1792 if (level.dauer_sieb<0)
1793 level.dauer_sieb = 0;
1794 else if (level.dauer_sieb>255)
1795 level.dauer_sieb = 255;
1797 else if (choice==13)
1799 level.dauer_ablenk += step;
1800 if (level.dauer_ablenk<0)
1801 level.dauer_ablenk = 0;
1802 else if (level.dauer_ablenk>255)
1803 level.dauer_ablenk = 255;
1805 else if (choice==14)
1807 level.edelsteine += step;
1808 if (level.edelsteine<0)
1809 level.edelsteine = 0;
1810 else if (level.edelsteine>999)
1811 level.edelsteine = 999;
1813 else if (choice==15)
1818 else if (level.time>999)
1821 else if (choice==16)
1824 if (lev_fieldx<MIN_LEV_FIELDX)
1825 lev_fieldx = MIN_LEV_FIELDX;
1826 else if (lev_fieldx>MAX_LEV_FIELDX)
1827 lev_fieldx = MAX_LEV_FIELDX;
1828 level.fieldx = lev_fieldx;
1830 else if (choice==17)
1833 if (lev_fieldy<MIN_LEV_FIELDY)
1834 lev_fieldy = MIN_LEV_FIELDY;
1835 else if (lev_fieldy>MAX_LEV_FIELDY)
1836 lev_fieldy = MAX_LEV_FIELDY;
1837 level.fieldy = lev_fieldy;
1841 DrawText(ED_COUNT_VALUE_XPOS,
1842 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1843 int2str(level.score[choice],3),FS_SMALL,FC_YELLOW);
1844 else if (choice==11)
1845 DrawText(ED_COUNT_VALUE_XPOS,
1846 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1847 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1848 else if (choice==12)
1849 DrawText(ED_COUNT_VALUE_XPOS,
1850 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1851 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1852 else if (choice==13)
1853 DrawText(ED_COUNT_VALUE_XPOS,
1854 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1855 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1856 else if (choice==14)
1857 DrawText(ED_COUNT_VALUE_XPOS,
1858 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1859 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1860 else if (choice==15)
1861 DrawText(ED_COUNT_VALUE_XPOS,
1862 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1863 int2str(level.time,3),FS_SMALL,FC_YELLOW);
1864 else if (choice==16)
1865 DrawText(ED_SIZE_VALUE_XPOS,
1866 ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1867 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1868 else if (choice==17)
1869 DrawText(ED_SIZE_VALUE_XPOS,
1870 ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1871 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1873 redraw_mask &= ~REDRAW_FIELD;
1875 XCopyArea(display,drawto,window,gc,
1876 ED_COUNT_VALUE_XPOS,
1877 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1878 3*FONT2_XSIZE,FONT2_YSIZE,
1879 ED_COUNT_VALUE_XPOS,
1880 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE);
1882 XCopyArea(display,drawto,window,gc,
1884 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE,
1885 3*FONT2_XSIZE,FONT2_YSIZE,
1887 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE);
1895 switch(CheckCtrlButtons(mx,my,button))
1897 case ED_BUTTON_EDIT:
1898 CloseDoor(DOOR_CLOSE_2);
1899 AdjustLevelScrollPosition();
1900 DrawMiniLevel(level_xpos,level_ypos);
1901 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1902 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1904 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1905 OpenDoor(DOOR_OPEN_2);
1906 edit_mode = ED_MODE_DRAWING;
1908 case ED_BUTTON_CLEAR:
1909 if (Request("Are you sure to clear this level ?",REQ_ASK))
1911 for(x=0;x<MAX_LEV_FIELDX;x++)
1912 for(y=0;y<MAX_LEV_FIELDY;y++)
1913 Feld[x][y] = EL_ERDREICH;
1914 DrawMiniLevel(level_xpos,level_ypos);
1917 case ED_BUTTON_UNDO:
1918 if (leveldir[leveldir_nr].readonly ||
1919 Request("Exit without saving ?",REQ_ASK | REQ_STAY_OPEN))
1921 CloseDoor(DOOR_CLOSE_ALL);
1922 game_status=MAINMENU;
1927 CloseDoor(DOOR_CLOSE_1);
1928 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1931 case ED_BUTTON_EXIT:
1933 int figur_vorhanden = FALSE;
1935 if (leveldir[leveldir_nr].readonly)
1937 Request("This level is read only !",REQ_CONFIRM);
1941 for(y=0;y<lev_fieldy;y++)
1942 for(x=0;x<lev_fieldx;x++)
1943 if (Feld[x][y] == EL_SPIELFIGUR ||
1944 Feld[x][y] == EL_SPIELER1 ||
1945 Feld[x][y] == EL_SP_MURPHY)
1946 figur_vorhanden = TRUE;
1948 if (!figur_vorhanden)
1949 Request("No Level without Gregor Mc Duffin please !",
1953 if (Request("Save this level and kill the old ?",
1954 REQ_ASK | REQ_STAY_OPEN))
1956 for(x=0;x<lev_fieldx;x++)
1957 for(y=0;y<lev_fieldy;y++)
1958 Ur[x][y]=Feld[x][y];
1959 SaveLevel(level_nr);
1961 CloseDoor(DOOR_CLOSE_ALL);
1962 game_status=MAINMENU;
1975 if (mx>=ED_COUNT_GADGET_XPOS &&
1976 mx<ED_COUNT_GADGET_XPOS+31*FONT2_XSIZE+10 &&
1977 my>=ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE &&
1978 my<ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE+ED_WIN_COUNT_YSIZE)
1983 DrawText(ED_COUNT_GADGET_XPOS+5,
1984 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1985 level.name,FS_SMALL,FC_GREEN);
1986 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1987 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1988 "<",FS_SMALL,FC_RED);
1995 name_typing = FALSE;
1996 DrawText(ED_COUNT_GADGET_XPOS+5,
1997 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1998 level.name,FS_SMALL,FC_YELLOW);
1999 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
2000 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2001 " ",FS_SMALL,FC_RED);
2005 if (mx>=SX+29*MINI_TILEX && mx<SX+30*MINI_TILEX &&
2006 my>=SY+26*MINI_TILEY && my<SY+27*MINI_TILEY)
2010 if (!button || button<1 || button>3)
2013 new_element = (button==1 ? new_element1 :
2014 button==2 ? new_element2 :
2015 button==3 ? new_element3 : 0);
2017 if (new_element != level.amoebe_inhalt)
2019 level.amoebe_inhalt = new_element;
2020 DrawMiniElement(29,26,new_element);
2024 if (mx>=SX+1*MINI_TILEX && mx<SX+(1+4*5)*MINI_TILEX &&
2025 my>=SY+2*MINI_TILEY && my<SY+(2+3)*MINI_TILEY)
2027 int x = (mx-SX-1*MINI_TILEX)/MINI_TILEX;
2028 int y = (my-SY-2*MINI_TILEY)/MINI_TILEY;
2033 if (i>=0 && i<43 && x>=0 && x<3 && y>=0 && y<3)
2035 if (button && !motion_status)
2036 in_field_pressed = TRUE;
2038 if (!button || !in_field_pressed || button<1 || button>3)
2041 new_element = (button==1 ? new_element1 :
2042 button==2 ? new_element2 :
2043 button==3 ? new_element3 : 0);
2045 if (new_element != level.mampfer_inhalt[i][x][y])
2047 level.mampfer_inhalt[i][x][y] = new_element;
2048 DrawMiniElement(1+5*i+x,2+y,new_element);
2051 else if (!motion_status)/* Mauszeiger nicht im Cruncher-Feld */
2052 in_field_pressed = FALSE;
2054 else if (!motion_status) /* Mauszeiger nicht im Cruncher-Feld */
2055 in_field_pressed = FALSE;
2059 last_button = button;
2064 void LevelNameTyping(KeySym key)
2066 unsigned char ascii = 0;
2067 int len = strlen(level.name);
2072 if (key>=XK_A && key<=XK_Z)
2073 ascii = 'A'+(char)(key-XK_A);
2074 else if (key>=XK_a && key<=XK_z)
2075 ascii = 'a'+(char)(key-XK_a);
2076 else if (key>=XK_0 && key<=XK_9)
2077 ascii = '0'+(char)(key-XK_0);
2079 else if (key>=XK_space && key<=XK_at)
2080 ascii = ' '+(char)(key-XK_space);
2081 else if (key==XK_Adiaeresis)
2083 else if (key==XK_Odiaeresis)
2085 else if (key==XK_Udiaeresis)
2087 else if (key==XK_adiaeresis)
2089 else if (key==XK_odiaeresis)
2091 else if (key==XK_udiaeresis)
2093 else if (key==XK_underscore)
2097 if (ascii && len<MAX_LEVNAMLEN-2)
2099 level.name[len] = ascii;
2100 level.name[len+1] = 0;
2103 DrawTextExt(drawto,gc,
2104 ED_COUNT_GADGET_XPOS+5,
2105 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2106 level.name,FS_SMALL,FC_GREEN);
2107 DrawTextExt(window,gc,
2108 ED_COUNT_GADGET_XPOS+5,
2109 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2110 level.name,FS_SMALL,FC_GREEN);
2111 DrawTextExt(drawto,gc,
2112 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2113 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2114 "<",FS_SMALL,FC_RED);
2115 DrawTextExt(window,gc,
2116 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2117 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2118 "<",FS_SMALL,FC_RED);
2120 else if ((key==XK_Delete || key==XK_BackSpace) && len>0)
2122 level.name[len-1] = 0;
2125 DrawTextExt(drawto,gc,
2126 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2127 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2128 "< ",FS_SMALL,FC_GREEN);
2129 DrawTextExt(window,gc,
2130 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2131 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2132 "< ",FS_SMALL,FC_GREEN);
2134 else if (key==XK_Return)
2136 DrawTextExt(drawto,gc,
2137 ED_COUNT_GADGET_XPOS+5,
2138 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2139 level.name,FS_SMALL,FC_YELLOW);
2140 DrawTextExt(window,gc,
2141 ED_COUNT_GADGET_XPOS+5,
2142 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2143 level.name,FS_SMALL,FC_YELLOW);
2144 DrawTextExt(drawto,gc,
2145 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2146 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2147 " ",FS_SMALL,FC_YELLOW);
2148 DrawTextExt(window,gc,
2149 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2150 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2151 " ",FS_SMALL,FC_YELLOW);
2153 name_typing = FALSE;
2157 static void DrawCounterValueField(int counter_id, int value)
2159 int x = SX + counterbutton_info[counter_id].x + ED_WIN_COUNT_XPOS;
2160 int y = SY + counterbutton_info[counter_id].y;
2162 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2163 DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS,
2164 DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS,
2165 ED_WIN_COUNT_XSIZE, ED_WIN_COUNT_YSIZE,
2168 DrawText(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2169 int2str(value, 3), FS_SMALL, FC_YELLOW);
2172 static void DrawDrawingWindow()
2175 UnmapLevelEditorWindowGadgets();
2176 AdjustLevelScrollPosition();
2177 AdjustEditorScrollbar(ED_CTRL_ID_SCROLL_HORIZONTAL);
2178 AdjustEditorScrollbar(ED_CTRL_ID_SCROLL_VERTICAL);
2179 DrawMiniLevel(level_xpos, level_ypos);
2180 MapMainDrawingArea();
2183 static void DrawElementContentAreas()
2185 int *num_areas = &MampferMax;
2186 int area_x = ED_AREA_ELEMCONT_XPOS / MINI_TILEX;
2187 int area_y = ED_AREA_ELEMCONT_YPOS / MINI_TILEY;
2188 int area_sx = SX + ED_AREA_ELEMCONT_XPOS;
2189 int area_sy = SY + ED_AREA_ELEMCONT_YPOS;
2192 for (i=0; i<MAX_ELEMCONT; i++)
2195 ElementContent[i][x][y] = level.mampfer_inhalt[i][x][y];
2197 for (i=0; i<MAX_ELEMCONT; i++)
2198 UnmapDrawingArea(ED_CTRL_ID_ELEMCONT_0 + i);
2200 /* display counter to choose number of element content areas */
2201 gadget_areas_value = num_areas;
2202 DrawCounterValueField(ED_COUNTER_ELEMCONT, *gadget_areas_value);
2203 x = counterbutton_info[ED_COUNTER_ELEMCONT].x + DXSIZE;
2204 y = counterbutton_info[ED_COUNTER_ELEMCONT].y;
2205 DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2206 FC_YELLOW, "number of content areas");
2207 MapCounterButtons(ED_COUNTER_ELEMCONT);
2209 /* delete content areas in case of reducing number of them */
2210 XFillRectangle(display, backbuffer, gc,
2211 SX, area_sy - MINI_TILEX,
2212 SXSIZE, 12 * MINI_TILEY);
2214 /* draw some decorative border for the objects */
2215 for (i=0; i<*num_areas; i++)
2219 DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
2222 XFillRectangle(display, drawto, gc,
2223 area_sx + 5 * (i % 4) * MINI_TILEX + MINI_TILEX/2 - 1,
2224 area_sy + 6 * (i / 4) * MINI_TILEY + MINI_TILEY/2 - 1,
2225 3 * MINI_TILEX + 2, 3 * MINI_TILEY + 2);
2228 /* copy border to the right location */
2229 XCopyArea(display, drawto, drawto, gc,
2230 area_sx, area_sy, (5 * 4 + 1) * MINI_TILEX, 12 * MINI_TILEY,
2231 area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
2233 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 0 * MINI_TILEY + 1,
2234 "Content", FS_SMALL, FC_YELLOW);
2235 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 1 * MINI_TILEY + 1,
2236 "when", FS_SMALL, FC_YELLOW);
2237 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 2 * MINI_TILEY + 1,
2238 "smashed", FS_SMALL, FC_YELLOW);
2240 for (i=0; i<*num_areas; i++)
2244 DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
2245 ElementContent[i][x][y]);
2247 DrawTextF(area_sx - SX + 5 * (i % 4) * MINI_TILEX + MINI_TILEX + 1,
2248 area_sy - SY + 6 * (i / 4) * MINI_TILEY + 4 * MINI_TILEY - 4,
2249 FC_YELLOW, "%d", i + 1);
2252 for (i=0; i<*num_areas; i++)
2253 MapDrawingArea(ED_CTRL_ID_ELEMCONT_0 + i);
2256 static void DrawAmoebaContentArea()
2258 int area_x = ED_AREA_ELEMCONT_XPOS / MINI_TILEX;
2259 int area_y = ED_AREA_ELEMCONT_YPOS / MINI_TILEY;
2260 int area_sx = SX + ED_AREA_ELEMCONT_XPOS;
2261 int area_sy = SY + ED_AREA_ELEMCONT_YPOS;
2264 ElementContent[0][0][0] = level.amoebe_inhalt;
2266 /* draw decorative border for the object */
2269 DrawMiniElement(area_x + x, area_y + y, EL_ERDREICH);
2271 XFillRectangle(display, drawto, gc,
2272 area_sx + MINI_TILEX/2 - 1, area_sy + MINI_TILEY/2 - 1,
2273 MINI_TILEX + 2, MINI_TILEY + 2);
2275 /* copy border to the right location */
2276 XCopyArea(display, drawto, drawto, gc,
2277 area_sx, area_sy, 3 * MINI_TILEX, 3 * MINI_TILEY,
2278 area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
2280 DrawText(area_sx + TILEX, area_sy + 1, "Content of amoeba",
2281 FS_SMALL, FC_YELLOW);
2283 DrawMiniElement(area_x, area_y, ElementContent[0][0][0]);
2285 MapDrawingArea(ED_CTRL_ID_AMOEBA_CONTENT);
2288 #define TEXT_COLLECTING "Score for collecting"
2289 #define TEXT_SMASHING "Score for smashing"
2290 #define TEXT_CRACKING "Score for cracking"
2291 #define TEXT_SPEED "Speed of amoeba growth"
2292 #define TEXT_DURATION "Duration when activated"
2294 static void DrawPropertiesWindow()
2297 int num_elements_in_level;
2303 } elements_with_counter[] =
2305 { EL_EDELSTEIN, &level.score[0], TEXT_COLLECTING },
2306 { EL_EDELSTEIN_BD, &level.score[0], TEXT_COLLECTING },
2307 { EL_EDELSTEIN_GELB,&level.score[0], TEXT_COLLECTING },
2308 { EL_EDELSTEIN_ROT, &level.score[0], TEXT_COLLECTING },
2309 { EL_EDELSTEIN_LILA,&level.score[0], TEXT_COLLECTING },
2310 { EL_DIAMANT, &level.score[1], TEXT_COLLECTING },
2311 { EL_KAEFER_R, &level.score[2], TEXT_SMASHING },
2312 { EL_KAEFER_O, &level.score[2], TEXT_SMASHING },
2313 { EL_KAEFER_L, &level.score[2], TEXT_SMASHING },
2314 { EL_KAEFER_U, &level.score[2], TEXT_SMASHING },
2315 { EL_BUTTERFLY_R, &level.score[2], TEXT_SMASHING },
2316 { EL_BUTTERFLY_O, &level.score[2], TEXT_SMASHING },
2317 { EL_BUTTERFLY_L, &level.score[2], TEXT_SMASHING },
2318 { EL_BUTTERFLY_U, &level.score[2], TEXT_SMASHING },
2319 { EL_FLIEGER_R, &level.score[3], TEXT_SMASHING },
2320 { EL_FLIEGER_O, &level.score[3], TEXT_SMASHING },
2321 { EL_FLIEGER_L, &level.score[3], TEXT_SMASHING },
2322 { EL_FLIEGER_U, &level.score[3], TEXT_SMASHING },
2323 { EL_FIREFLY_R, &level.score[3], TEXT_SMASHING },
2324 { EL_FIREFLY_O, &level.score[3], TEXT_SMASHING },
2325 { EL_FIREFLY_L, &level.score[3], TEXT_SMASHING },
2326 { EL_FIREFLY_U, &level.score[3], TEXT_SMASHING },
2327 { EL_MAMPFER, &level.score[4], TEXT_SMASHING },
2328 { EL_MAMPFER2, &level.score[4], TEXT_SMASHING },
2329 { EL_ROBOT, &level.score[5], TEXT_SMASHING },
2330 { EL_PACMAN_R, &level.score[6], TEXT_SMASHING },
2331 { EL_PACMAN_O, &level.score[6], TEXT_SMASHING },
2332 { EL_PACMAN_L, &level.score[6], TEXT_SMASHING },
2333 { EL_PACMAN_U, &level.score[6], TEXT_SMASHING },
2334 { EL_KOKOSNUSS, &level.score[7], TEXT_CRACKING },
2335 { EL_DYNAMIT_AUS, &level.score[8], TEXT_COLLECTING },
2336 { EL_SCHLUESSEL1, &level.score[9], TEXT_COLLECTING },
2337 { EL_SCHLUESSEL2, &level.score[9], TEXT_COLLECTING },
2338 { EL_SCHLUESSEL3, &level.score[9], TEXT_COLLECTING },
2339 { EL_SCHLUESSEL4, &level.score[9], TEXT_COLLECTING },
2340 { EL_AMOEBE_NASS, &level.tempo_amoebe, TEXT_SPEED },
2341 { EL_AMOEBE_NORM, &level.tempo_amoebe, TEXT_SPEED },
2342 { EL_AMOEBE_VOLL, &level.tempo_amoebe, TEXT_SPEED },
2343 { EL_AMOEBE_BD, &level.tempo_amoebe, TEXT_SPEED },
2344 { EL_SIEB_INAKTIV, &level.dauer_sieb, TEXT_DURATION },
2345 { EL_ABLENK_AUS, &level.dauer_ablenk, TEXT_DURATION },
2350 UnmapLevelEditorWindowGadgets();
2352 /* draw some decorative border for the object */
2355 DrawMiniElement(2 + x , 2 + y, EL_ERDREICH);
2357 XFillRectangle(display, drawto, gc,
2358 SX + TILEX + MINI_TILEX/2 - 1,
2359 SY + TILEY + MINI_TILEY/2 - 1,
2360 TILEX + 2, TILEY + 2);
2362 /* copy border to the right location */
2363 XCopyArea(display, drawto, drawto, gc,
2364 SX + TILEX, SY + TILEY,
2365 2 * TILEX, 2 * TILEY,
2366 SX + TILEX - MINI_TILEX/2, SY + TILEY - MINI_TILEY/2);
2368 DrawGraphic(1, 1, el2gfx(properties_element));
2369 DrawText(SX + 3*TILEX, SY + 5*TILEY/4, "Element Properties",
2370 FS_SMALL, FC_YELLOW);
2372 num_elements_in_level = 0;
2373 for (y=0; y<lev_fieldy; y++)
2374 for (x=0; x<lev_fieldx; x++)
2375 if (Feld[x][y] == properties_element)
2376 num_elements_in_level++;
2378 DrawTextF(ED_PROPERTIES_XPOS, 5*TILEY, FC_YELLOW, "%d x contained in level",
2379 num_elements_in_level);
2381 /* check if there are elements where a score can be chosen for */
2382 for (i=0; elements_with_counter[i].element != -1; i++)
2384 if (elements_with_counter[i].element == properties_element)
2386 int x = counterbutton_info[ED_COUNTER_SCORE].x + DXSIZE;
2387 int y = counterbutton_info[ED_COUNTER_SCORE].y;
2389 gadget_score_value = elements_with_counter[i].counter_value;
2390 DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value);
2391 DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2392 FC_YELLOW, elements_with_counter[i].text);
2393 MapCounterButtons(ED_COUNTER_SCORE);
2398 if (HAS_CONTENT(properties_element))
2400 if (IS_AMOEBOID(properties_element))
2401 DrawAmoebaContentArea();
2403 DrawElementContentAreas();
2406 /* TEST ONLY: level name text input gadget */
2407 MapTextInputGadget(ED_CTRL_ID_LEVEL_NAME);
2410 static void swap_numbers(int *i1, int *i2)
2418 static void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
2430 static void DrawLineElement(int sx, int sy, int element, boolean change_level)
2432 int lx = sx + level_xpos;
2433 int ly = sy + level_ypos;
2435 DrawMiniElement(sx, sy, (element < 0 ? Feld[lx][ly] : element));
2438 Feld[lx][ly] = element;
2441 static void DrawLine(int from_x, int from_y, int to_x, int to_y,
2442 int element, boolean change_level)
2444 if (from_y == to_y) /* horizontal line */
2450 swap_numbers(&from_x, &to_x);
2452 for (x=from_x; x<=to_x; x++)
2453 DrawLineElement(x, y, element, change_level);
2455 else if (from_x == to_x) /* vertical line */
2461 swap_numbers(&from_y, &to_y);
2463 for (y=from_y; y<=to_y; y++)
2464 DrawLineElement(x, y, element, change_level);
2466 else /* diagonal line */
2468 int len_x = ABS(to_x - from_x);
2469 int len_y = ABS(to_y - from_y);
2472 if (len_y < len_x) /* a < 1 */
2474 float a = (float)len_y / (float)len_x;
2477 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2479 for (x=0; x<=len_x; x++)
2481 int y = (int)(a * x + 0.5) * (to_y < from_y ? -1 : +1);
2483 DrawLineElement(from_x + x, from_y + y, element, change_level);
2488 float a = (float)len_x / (float)len_y;
2491 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2493 for (y=0; y<=len_y; y++)
2495 int x = (int)(a * y + 0.5) * (to_x < from_x ? -1 : +1);
2497 DrawLineElement(from_x + x, from_y + y, element, change_level);
2503 static void DrawRectangle(int from_x, int from_y, int to_x, int to_y,
2504 int element, boolean change_level)
2506 DrawLine(from_x, from_y, from_x, to_y, element, change_level);
2507 DrawLine(from_x, to_y, to_x, to_y, element, change_level);
2508 DrawLine(to_x, to_y, to_x, from_y, element, change_level);
2509 DrawLine(to_x, from_y, from_x, from_y, element, change_level);
2512 static void DrawFilledBox(int from_x, int from_y, int to_x, int to_y,
2513 int element, boolean change_level)
2518 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2520 for (y=from_y; y<=to_y; y++)
2521 DrawLine(from_x, y, to_x, y, element, change_level);
2524 static void DrawAreaBorder(int from_x, int from_y, int to_x, int to_y)
2526 int from_sx, from_sy;
2530 swap_numbers(&from_x, &to_x);
2533 swap_numbers(&from_y, &to_y);
2535 from_sx = SX + from_x * MINI_TILEX;
2536 from_sy = SY + from_y * MINI_TILEY;
2537 to_sx = SX + to_x * MINI_TILEX + MINI_TILEX - 1;
2538 to_sy = SY + to_y * MINI_TILEY + MINI_TILEY - 1;
2540 XSetForeground(display, gc, WhitePixel(display, screen));
2542 XDrawLine(display, drawto, gc, from_sx, from_sy, to_sx, from_sy);
2543 XDrawLine(display, drawto, gc, to_sx, from_sy, to_sx, to_sy);
2544 XDrawLine(display, drawto, gc, to_sx, to_sy, from_sx, to_sy);
2545 XDrawLine(display, drawto, gc, from_sx, to_sy, from_sx, from_sy);
2547 XSetForeground(display, gc, BlackPixel(display, screen));
2549 if (from_x == to_x && from_y == to_y)
2550 MarkTileDirty(from_x/2, from_y/2);
2552 redraw_mask |= REDRAW_FIELD;
2555 static void SelectArea(int from_x, int from_y, int to_x, int to_y,
2556 int element, boolean change_level)
2558 if (element == -1 || change_level)
2559 DrawRectangle(from_x, from_y, to_x, to_y, -1, FALSE);
2561 DrawAreaBorder(from_x, from_y, to_x, to_y);
2564 /* values for CopyBrushExt() */
2565 #define CB_AREA_TO_BRUSH 0
2566 #define CB_BRUSH_TO_CURSOR 1
2567 #define CB_BRUSH_TO_LEVEL 2
2568 #define CB_DELETE_OLD_CURSOR 3
2570 static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y,
2571 int button, int mode)
2573 static short brush_buffer[ED_FIELDX][ED_FIELDY];
2574 static int brush_width, brush_height;
2575 static int last_cursor_x = -1, last_cursor_y = -1;
2576 static boolean delete_old_brush;
2580 if (mode == CB_DELETE_OLD_CURSOR && !delete_old_brush)
2583 new_element = (button == 1 ? new_element1 :
2584 button == 2 ? new_element2 :
2585 button == 3 ? new_element3 : 0);
2587 if (mode == CB_AREA_TO_BRUSH)
2589 int from_lx, from_ly;
2592 swap_numbers(&from_x, &to_x);
2595 swap_numbers(&from_y, &to_y);
2597 brush_width = to_x - from_x + 1;
2598 brush_height = to_y - from_y + 1;
2600 from_lx = from_x + level_xpos;
2601 from_ly = from_y + level_ypos;
2603 for (y=0; y<brush_height; y++)
2605 for (x=0; x<brush_width; x++)
2607 brush_buffer[x][y] = Feld[from_lx + x][from_ly + y];
2610 DrawLineElement(from_x + x, from_y + y, new_element, TRUE);
2615 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2617 delete_old_brush = FALSE;
2619 else if (mode == CB_BRUSH_TO_CURSOR || mode == CB_DELETE_OLD_CURSOR ||
2620 mode == CB_BRUSH_TO_LEVEL)
2622 int cursor_x = (mode == CB_DELETE_OLD_CURSOR ? last_cursor_x : from_x);
2623 int cursor_y = (mode == CB_DELETE_OLD_CURSOR ? last_cursor_y : from_y);
2624 int cursor_from_x = cursor_x - brush_width / 2;
2625 int cursor_from_y = cursor_y - brush_height / 2;
2626 int border_from_x = cursor_x, border_from_y = cursor_y;
2627 int border_to_x = cursor_x, border_to_y = cursor_y;
2629 if (mode != CB_DELETE_OLD_CURSOR && delete_old_brush)
2630 CopyBrushExt(0, 0, 0, 0, 0, CB_DELETE_OLD_CURSOR);
2632 if (!IN_LEV_FIELD(cursor_x + level_xpos, cursor_y + level_ypos))
2634 delete_old_brush = FALSE;
2638 for (y=0; y<brush_height; y++)
2640 for (x=0; x<brush_width; x++)
2642 int sx = cursor_from_x + x;
2643 int sy = cursor_from_y + y;
2644 int lx = sx + level_xpos;
2645 int ly = sy + level_ypos;
2646 boolean change_level = (mode == CB_BRUSH_TO_LEVEL);
2647 int element = (mode == CB_DELETE_OLD_CURSOR ? -1 :
2648 mode == CB_BRUSH_TO_CURSOR || button == 1 ?
2649 brush_buffer[x][y] : new_element);
2651 if (IN_LEV_FIELD(lx, ly) &&
2652 sx >=0 && sx < ED_FIELDX && sy >=0 && sy < ED_FIELDY)
2654 if (sx < border_from_x)
2656 else if (sx > border_to_x)
2658 if (sy < border_from_y)
2660 else if (sy > border_to_y)
2663 DrawLineElement(sx, sy, element, change_level);
2669 printf("%d, %d - %d, %d in level and screen\n",
2670 border_from_x, border_from_y, border_to_x, border_to_y);
2673 if (mode != CB_DELETE_OLD_CURSOR)
2674 DrawAreaBorder(border_from_x, border_from_y, border_to_x, border_to_y);
2677 if (mode == CB_BRUSH_TO_LEVEL)
2678 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2681 last_cursor_x = cursor_x;
2682 last_cursor_y = cursor_y;
2683 delete_old_brush = TRUE;
2687 static void CopyAreaToBrush(int from_x, int from_y, int to_x, int to_y,
2690 CopyBrushExt(from_x, from_y, to_x, to_y, button, CB_AREA_TO_BRUSH);
2693 static void CopyBrushToLevel(int x, int y, int button)
2695 CopyBrushExt(x, y, 0, 0, button, CB_BRUSH_TO_LEVEL);
2698 static void CopyBrushToCursor(int x, int y)
2700 CopyBrushExt(x, y, 0, 0, 0, CB_BRUSH_TO_CURSOR);
2703 static void DeleteBrushFromCursor()
2705 CopyBrushExt(0, 0, 0, 0, 0, CB_DELETE_OLD_CURSOR);
2708 static void FloodFill(int from_x, int from_y, int fill_element)
2712 static int check[4][2] = { {-1,0}, {0,-1}, {1,0}, {0,1} };
2713 static int safety = 0;
2715 /* check if starting field still has the desired content */
2716 if (Feld[from_x][from_y] == fill_element)
2721 if (safety > lev_fieldx*lev_fieldy)
2722 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
2724 old_element = Feld[from_x][from_y];
2725 Feld[from_x][from_y] = fill_element;
2729 x = from_x + check[i][0];
2730 y = from_y + check[i][1];
2732 if (IN_LEV_FIELD(x,y) && Feld[x][y] == old_element)
2733 FloodFill(x, y, fill_element);
2739 /* values for DrawLevelText() modes */
2741 #define TEXT_SETCURSOR 1
2742 #define TEXT_WRITECHAR 2
2743 #define TEXT_BACKSPACE 3
2744 #define TEXT_NEWLINE 4
2747 static void DrawLevelText(int sx, int sy, char letter, int mode)
2749 static short delete_buffer[MAX_LEV_FIELDX];
2750 static int start_sx, start_sy;
2751 static int last_sx, last_sy;
2752 static boolean typing = FALSE;
2753 int letter_element = EL_CHAR_ASCII0 + letter;
2756 /* map lower case letters to upper case and convert special characters */
2757 if (letter >= 'a' && letter <= 'z')
2758 letter_element = EL_CHAR_ASCII0 + letter + (int)('A' - 'a');
2759 else if (letter == 'ä' || letter == 'Ä')
2760 letter_element = EL_CHAR_AE;
2761 else if (letter == 'ö' || letter == 'Ö')
2762 letter_element = EL_CHAR_OE;
2763 else if (letter == 'ü' || letter == 'Ü')
2764 letter_element = EL_CHAR_UE;
2765 else if (letter == '^')
2766 letter_element = EL_CHAR_COPY;
2768 letter_element = EL_CHAR_ASCII0 + letter;
2770 if (mode != TEXT_INIT)
2775 if (mode != TEXT_SETCURSOR)
2781 lx = last_sx + level_xpos;
2782 ly = last_sy + level_ypos;
2789 DrawLevelText(0, 0, 0, TEXT_END);
2792 start_sx = last_sx = sx;
2793 start_sy = last_sy = sy;
2794 DrawLevelText(sx, sy, 0, TEXT_SETCURSOR);
2797 case TEXT_SETCURSOR:
2798 DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
2799 DrawAreaBorder(sx, sy, sx, sy);
2804 case TEXT_WRITECHAR:
2805 if (letter_element >= EL_CHAR_START && letter_element <= EL_CHAR_END)
2807 delete_buffer[sx - start_sx] = Feld[lx][ly];
2808 Feld[lx][ly] = letter_element;
2810 if (sx + 1 < ED_FIELDX && lx + 1 < lev_fieldx)
2811 DrawLevelText(sx + 1, sy, 0, TEXT_SETCURSOR);
2812 else if (sy + 1 < ED_FIELDY && ly + 1 < lev_fieldy)
2813 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
2815 DrawLevelText(0, 0, 0, TEXT_END);
2819 case TEXT_BACKSPACE:
2822 Feld[lx - 1][ly] = delete_buffer[sx - start_sx - 1];
2823 DrawMiniElement(sx - 1, sy, new_element3);
2824 DrawLevelText(sx - 1, sy, 0, TEXT_SETCURSOR);
2829 if (sy + 1 < ED_FIELDY - 1 && ly + 1 < lev_fieldy - 1)
2830 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
2832 DrawLevelText(0, 0, 0, TEXT_END);
2836 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2837 DrawMiniElement(sx, sy, Feld[lx][ly]);
2846 static void SetTextCursor(int unused_sx, int unused_sy, int sx, int sy,
2847 int element, boolean change_level)
2849 int lx = sx + level_xpos;
2850 int ly = sy + level_ypos;
2853 DrawMiniElement(sx, sy, Feld[lx][ly]);
2855 DrawAreaBorder(sx, sy, sx, sy);
2858 static void CopyLevelToUndoBuffer(int mode)
2860 static boolean accumulated_undo = FALSE;
2861 boolean new_undo_buffer_position = TRUE;
2866 case UNDO_IMMEDIATE:
2867 accumulated_undo = FALSE;
2870 case UNDO_ACCUMULATE:
2871 if (accumulated_undo)
2872 new_undo_buffer_position = FALSE;
2873 accumulated_undo = TRUE;
2880 if (new_undo_buffer_position)
2882 /* new position in undo buffer ring */
2883 undo_buffer_position = (undo_buffer_position + 1) % NUM_UNDO_STEPS;
2885 if (undo_buffer_steps < NUM_UNDO_STEPS - 1)
2886 undo_buffer_steps++;
2889 for(x=0; x<lev_fieldx; x++)
2890 for(y=0; y<lev_fieldy; y++)
2891 UndoBuffer[undo_buffer_position][x][y] = Feld[x][y];
2894 printf("level saved to undo buffer\n");
2899 static void RandomPlacement(int button)
2904 new_element = (button == 1 ? new_element1 :
2905 button == 2 ? new_element2 :
2906 button == 3 ? new_element3 : 0);
2908 if (random_placement_method == RANDOM_USE_PERCENTAGE)
2910 for(x=0; x<lev_fieldx; x++)
2911 for(y=0; y<lev_fieldy; y++)
2912 if (RND(100) < random_placement_percentage)
2913 Feld[x][y] = new_element;
2917 int elements_left = random_placement_num_objects;
2919 while (elements_left > 0)
2921 x = RND(lev_fieldx);
2922 y = RND(lev_fieldy);
2924 if (Feld[x][y] != new_element)
2926 Feld[x][y] = new_element;
2932 DrawMiniLevel(level_xpos, level_ypos);
2933 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2936 void WrapLevel(int dx, int dy)
2938 int wrap_dx = lev_fieldx - dx;
2939 int wrap_dy = lev_fieldy - dy;
2942 for(x=0; x<lev_fieldx; x++)
2943 for(y=0; y<lev_fieldy; y++)
2944 FieldBackup[x][y] = Feld[x][y];
2946 for(x=0; x<lev_fieldx; x++)
2947 for(y=0; y<lev_fieldy; y++)
2949 FieldBackup[(x + wrap_dx) % lev_fieldx][(y + wrap_dy) % lev_fieldy];
2951 DrawMiniLevel(level_xpos, level_ypos);
2952 CopyLevelToUndoBuffer(UNDO_ACCUMULATE);
2955 static void HandleDrawingAreas(struct GadgetInfo *gi)
2957 static boolean started_inside_drawing_area = FALSE;
2958 int id = gi->custom_id;
2959 boolean inside_drawing_area = !gi->event.off_borders;
2960 boolean button_press_event;
2961 boolean button_release_event;
2962 boolean draw_level = (id == ED_CTRL_ID_DRAWING_LEVEL);
2964 int button = gi->event.button;
2965 int sx = gi->event.x, sy = gi->event.y;
2966 int min_sx = 0, min_sy = 0;
2967 int max_sx = gi->drawing.area_xsize - 1, max_sy = gi->drawing.area_ysize - 1;
2969 int min_lx = 0, min_ly = 0;
2970 int max_lx = lev_fieldx - 1, max_ly = lev_fieldy - 1;
2973 /* handle info callback for each invocation of action callback */
2974 gi->callback_info(gi);
2977 if (edit_mode != ED_MODE_DRAWING)
2981 button_press_event = (gi->event.type == GD_EVENT_PRESSED);
2982 button_release_event = (gi->event.type == GD_EVENT_RELEASED);
2984 /* make sure to stay inside drawing area boundaries */
2985 sx = (sx < min_sx ? min_sx : sx > max_sx ? max_sx : sx);
2986 sy = (sy < min_sy ? min_sy : sy > max_sy ? max_sy : sy);
2990 /* get positions inside level field */
2991 lx = sx + level_xpos;
2992 ly = sy + level_ypos;
2994 /* make sure to stay inside level field boundaries */
2995 lx = (lx < min_lx ? min_lx : lx > max_lx ? max_lx : lx);
2996 ly = (ly < min_ly ? min_ly : ly > max_ly ? max_ly : ly);
2998 /* correct drawing area positions accordingly */
2999 sx = lx - level_xpos;
3000 sy = ly - level_ypos;
3003 if (button_press_event)
3004 started_inside_drawing_area = inside_drawing_area;
3006 if (!started_inside_drawing_area)
3009 if (!button && !button_release_event)
3012 new_element = (button == 1 ? new_element1 :
3013 button == 2 ? new_element2 :
3014 button == 3 ? new_element3 : 0);
3016 if (!draw_level && drawing_function != ED_CTRL_ID_SINGLE_ITEMS)
3019 switch (drawing_function)
3021 case ED_CTRL_ID_SINGLE_ITEMS:
3024 if (button_release_event)
3025 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3030 if (draw_with_brush)
3031 CopyBrushToLevel(sx, sy, button);
3032 else if (new_element != Feld[lx][ly])
3034 if (new_element == EL_SPIELFIGUR)
3036 /* remove player at old position */
3037 for(y=0; y<lev_fieldy; y++)
3039 for(x=0; x<lev_fieldx; x++)
3041 if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1)
3043 Feld[x][y] = EL_LEERRAUM;
3044 if (x - level_xpos >= 0 && x - level_xpos < ED_FIELDX &&
3045 y - level_ypos >= 0 && y - level_ypos < ED_FIELDY)
3046 DrawMiniElement(x - level_xpos, y - level_ypos,
3053 Feld[lx][ly] = new_element;
3054 DrawMiniElement(sx, sy, new_element);
3059 DrawMiniGraphicExt(drawto, gc,
3060 gi->x + sx * MINI_TILEX,
3061 gi->y + sy * MINI_TILEY,
3062 el2gfx(new_element));
3063 DrawMiniGraphicExt(window, gc,
3064 gi->x + sx * MINI_TILEX,
3065 gi->y + sy * MINI_TILEY,
3066 el2gfx(new_element));
3068 if (id == ED_CTRL_ID_AMOEBA_CONTENT)
3069 level.amoebe_inhalt = new_element;
3070 else if (id >= ED_CTRL_ID_ELEMCONT_0 && id <= ED_CTRL_ID_ELEMCONT_7)
3071 level.mampfer_inhalt[id - ED_CTRL_ID_ELEMCONT_0][sx][sy] =
3076 case ED_CTRL_ID_CONNECTED_ITEMS:
3078 static int last_sx = -1;
3079 static int last_sy = -1;
3081 if (button_release_event)
3082 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3086 if (!button_press_event)
3087 DrawLine(last_sx, last_sy, sx, sy, new_element, TRUE);
3095 case ED_CTRL_ID_LINE:
3096 case ED_CTRL_ID_RECTANGLE:
3097 case ED_CTRL_ID_FILLED_BOX:
3098 case ED_CTRL_ID_GRAB_BRUSH:
3099 case ED_CTRL_ID_TEXT:
3101 static int last_sx = -1;
3102 static int last_sy = -1;
3103 static int start_sx = -1;
3104 static int start_sy = -1;
3105 void (*draw_func)(int, int, int, int, int, boolean);
3107 if (drawing_function == ED_CTRL_ID_LINE)
3108 draw_func = DrawLine;
3109 else if (drawing_function == ED_CTRL_ID_RECTANGLE)
3110 draw_func = DrawRectangle;
3111 else if (drawing_function == ED_CTRL_ID_FILLED_BOX)
3112 draw_func = DrawFilledBox;
3113 else if (drawing_function == ED_CTRL_ID_GRAB_BRUSH)
3114 draw_func = SelectArea;
3115 else /* (drawing_function == ED_CTRL_ID_TEXT) */
3116 draw_func = SetTextCursor;
3118 if (button_press_event)
3120 draw_func(sx, sy, sx, sy, new_element, FALSE);
3121 start_sx = last_sx = sx;
3122 start_sy = last_sy = sy;
3124 if (drawing_function == ED_CTRL_ID_TEXT)
3125 DrawLevelText(0, 0, 0, TEXT_END);
3127 else if (button_release_event)
3129 draw_func(start_sx, start_sy, sx, sy, new_element, TRUE);
3130 if (drawing_function == ED_CTRL_ID_GRAB_BRUSH)
3132 CopyAreaToBrush(start_sx, start_sy, sx, sy, button);
3133 CopyBrushToCursor(sx, sy);
3134 ClickOnGadget(level_editor_gadget[ED_CTRL_ID_SINGLE_ITEMS]);
3135 draw_with_brush = TRUE;
3137 else if (drawing_function == ED_CTRL_ID_TEXT)
3138 DrawLevelText(sx, sy, 0, TEXT_INIT);
3140 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3142 else if (last_sx != sx || last_sy != sy)
3144 draw_func(start_sx, start_sy, last_sx, last_sy, -1, FALSE);
3145 draw_func(start_sx, start_sy, sx, sy, new_element, FALSE);
3155 case ED_CTRL_ID_TEXT:
3157 DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
3158 DrawAreaBorder(sx, sy, sx, sy);
3163 if (button_press_event)
3164 DrawLevelText(sx, sy, 0, TEXT_INIT);
3170 case ED_CTRL_ID_FLOOD_FILL:
3171 if (button_press_event && Feld[lx][ly] != new_element)
3173 FloodFill(lx, ly, new_element);
3174 DrawMiniLevel(level_xpos, level_ypos);
3175 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3179 case ED_CTRL_ID_PICK_ELEMENT:
3180 if (button_press_event)
3181 PickDrawingElement(button, Feld[lx][ly]);
3182 if (button_release_event)
3183 ClickOnGadget(level_editor_gadget[last_drawing_function]);
3191 static void HandleCounterButtons(struct GadgetInfo *gi)
3193 int id = gi->custom_id;
3194 int button = gi->event.button;
3195 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
3199 case ED_CTRL_ID_SCORE_DOWN:
3200 case ED_CTRL_ID_SCORE_UP:
3201 *gadget_score_value += (id == ED_CTRL_ID_SCORE_DOWN ? -step : step);
3202 if (*gadget_score_value < 0)
3203 *gadget_score_value = 0;
3204 else if (*gadget_score_value > 255)
3205 *gadget_score_value = 255;
3207 DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value);
3210 case ED_CTRL_ID_ELEMCONT_DOWN:
3211 case ED_CTRL_ID_ELEMCONT_UP:
3212 *gadget_areas_value += (id == ED_CTRL_ID_ELEMCONT_DOWN ? -step : step);
3213 if (*gadget_areas_value < 1)
3214 *gadget_areas_value = 1;
3215 else if (*gadget_areas_value > MAX_ELEMCONT)
3216 *gadget_areas_value = MAX_ELEMCONT;
3218 DrawCounterValueField(ED_COUNTER_ELEMCONT, *gadget_areas_value);
3219 DrawElementContentAreas();
3227 static void HandleControlButtons(struct GadgetInfo *gi)
3229 int id = gi->custom_id;
3230 int button = gi->event.button;
3231 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
3233 int player_present = FALSE;
3234 int level_changed = FALSE;
3237 new_element = (button == 1 ? new_element1 :
3238 button == 2 ? new_element2 :
3239 button == 3 ? new_element3 : 0);
3241 if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT)
3242 DrawLevelText(0, 0, 0, TEXT_END);
3244 if (id < ED_NUM_CTRL1_BUTTONS && id != ED_CTRL_ID_PROPERTIES &&
3245 edit_mode != ED_MODE_DRAWING)
3247 DrawDrawingWindow();
3248 edit_mode = ED_MODE_DRAWING;
3253 case ED_CTRL_ID_SCROLL_LEFT:
3254 if (level_xpos >= 0)
3256 int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL;
3257 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3258 struct GadgetScrollbar *gs = &gi->scrollbar;
3260 if (lev_fieldx < ED_FIELDX - 2)
3264 if (level_xpos < -1)
3267 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_RIGHT);
3269 DrawMiniLevel(level_xpos, level_ypos);
3271 AdjustScrollbar(gi, gs->items_max, level_xpos + 1);
3275 case ED_CTRL_ID_SCROLL_RIGHT:
3276 if (level_xpos <= lev_fieldx - ED_FIELDX)
3278 int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL;
3279 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3280 struct GadgetScrollbar *gs = &gi->scrollbar;
3282 if (lev_fieldx < ED_FIELDX - 2)
3286 if (level_xpos > lev_fieldx - ED_FIELDX + 1)
3287 level_xpos = lev_fieldx - ED_FIELDX + 1;
3289 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_LEFT);
3291 DrawMiniLevel(level_xpos, level_ypos);
3293 AdjustScrollbar(gi, gs->items_max, level_xpos + 1);
3297 case ED_CTRL_ID_SCROLL_UP:
3298 if (level_ypos >= 0)
3300 int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL;
3301 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3302 struct GadgetScrollbar *gs = &gi->scrollbar;
3304 if (lev_fieldy < ED_FIELDY - 2)
3308 if (level_ypos < -1)
3311 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_DOWN);
3313 DrawMiniLevel(level_xpos, level_ypos);
3315 AdjustScrollbar(gi, gs->items_max, level_ypos + 1);
3319 case ED_CTRL_ID_SCROLL_DOWN:
3320 if (level_ypos <= lev_fieldy - ED_FIELDY)
3322 int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL;
3323 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3324 struct GadgetScrollbar *gs = &gi->scrollbar;
3326 if (lev_fieldy < ED_FIELDY - 2)
3330 if (level_ypos > lev_fieldy - ED_FIELDY + 1)
3331 level_ypos = lev_fieldy - ED_FIELDY + 1;
3333 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_UP);
3335 DrawMiniLevel(level_xpos, level_ypos);
3337 AdjustScrollbar(gi, gs->items_max, level_ypos + 1);
3341 case ED_CTRL_ID_SCROLL_HORIZONTAL:
3342 level_xpos = gi->event.item_position - 1;
3343 DrawMiniLevel(level_xpos, level_ypos);
3346 case ED_CTRL_ID_SCROLL_VERTICAL:
3347 level_ypos = gi->event.item_position - 1;
3348 DrawMiniLevel(level_xpos, level_ypos);
3351 case ED_CTRL_ID_WRAP_LEFT:
3352 WrapLevel(-step, 0);
3355 case ED_CTRL_ID_WRAP_RIGHT:
3359 case ED_CTRL_ID_WRAP_UP:
3360 WrapLevel(0, -step);
3363 case ED_CTRL_ID_WRAP_DOWN:
3367 case ED_CTRL_ID_SINGLE_ITEMS:
3368 case ED_CTRL_ID_CONNECTED_ITEMS:
3369 case ED_CTRL_ID_LINE:
3370 case ED_CTRL_ID_TEXT:
3371 case ED_CTRL_ID_RECTANGLE:
3372 case ED_CTRL_ID_FILLED_BOX:
3373 case ED_CTRL_ID_FLOOD_FILL:
3374 case ED_CTRL_ID_GRAB_BRUSH:
3375 case ED_CTRL_ID_PICK_ELEMENT:
3376 last_drawing_function = drawing_function;
3377 drawing_function = id;
3378 draw_with_brush = FALSE;
3381 case ED_CTRL_ID_RANDOM_PLACEMENT:
3382 RandomPlacement(button);
3385 case ED_CTRL_ID_PROPERTIES:
3386 if (edit_mode != ED_MODE_PROPERTIES)
3388 properties_element = new_element;
3389 DrawPropertiesWindow();
3390 edit_mode = ED_MODE_PROPERTIES;
3394 DrawDrawingWindow();
3395 edit_mode = ED_MODE_DRAWING;
3399 case ED_CTRL_ID_UNDO:
3400 if (undo_buffer_steps == 0)
3402 Request("Undo buffer empty !", REQ_CONFIRM);
3406 undo_buffer_position =
3407 (undo_buffer_position - 1 + NUM_UNDO_STEPS) % NUM_UNDO_STEPS;
3408 undo_buffer_steps--;
3410 for(x=0; x<lev_fieldx; x++)
3411 for(y=0; y<lev_fieldy; y++)
3412 Feld[x][y] = UndoBuffer[undo_buffer_position][x][y];
3413 DrawMiniLevel(level_xpos,level_ypos);
3416 case ED_CTRL_ID_INFO:
3417 if (edit_mode != ED_MODE_INFO)
3419 DrawControlWindow();
3420 edit_mode = ED_MODE_INFO;
3424 DrawDrawingWindow();
3425 edit_mode = ED_MODE_DRAWING;
3429 case ED_CTRL_ID_CLEAR:
3430 for(x=0; x<MAX_LEV_FIELDX; x++)
3431 for(y=0; y<MAX_LEV_FIELDY; y++)
3432 Feld[x][y] = new_element3;
3433 CopyLevelToUndoBuffer(ED_CTRL_ID_CLEAR);
3435 DrawMiniLevel(level_xpos, level_ypos);
3438 case ED_CTRL_ID_SAVE:
3439 if (leveldir[leveldir_nr].readonly)
3441 Request("This level is read only !", REQ_CONFIRM);
3445 for(y=0; y<lev_fieldy; y++)
3446 for(x=0; x<lev_fieldx; x++)
3447 if (Feld[x][y] != Ur[x][y])
3448 level_changed = TRUE;
3450 if (0 && !level_changed)
3452 Request("Level has not changed !", REQ_CONFIRM);
3456 for(y=0; y<lev_fieldy; y++)
3457 for(x=0; x<lev_fieldx; x++)
3458 if (Feld[x][y] == EL_SPIELFIGUR ||
3459 Feld[x][y] == EL_SPIELER1 ||
3460 Feld[x][y] == EL_SP_MURPHY)
3461 player_present = TRUE;
3463 if (!player_present)
3464 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
3467 if (Request("Save this level and kill the old ?", REQ_ASK))
3469 for(x=0; x<lev_fieldx; x++)
3470 for(y=0; y<lev_fieldy; y++)
3471 Ur[x][y] = Feld[x][y];
3472 SaveLevel(level_nr);
3477 case ED_CTRL_ID_TEST:
3478 for(y=0; y<lev_fieldy; y++)
3479 for(x=0; x<lev_fieldx; x++)
3480 if (Feld[x][y] == EL_SPIELFIGUR ||
3481 Feld[x][y] == EL_SPIELER1 ||
3482 Feld[x][y] == EL_SP_MURPHY)
3483 player_present = TRUE;
3485 if (!player_present)
3486 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
3489 for(x=0; x<lev_fieldx; x++)
3490 for(y=0; y<lev_fieldy; y++)
3491 FieldBackup[x][y] = Ur[x][y];
3493 for(x=0; x<lev_fieldx; x++)
3494 for(y=0; y<lev_fieldy; y++)
3495 Ur[x][y] = Feld[x][y];
3497 UnmapLevelEditorGadgets();
3499 /* draw smaller door */
3500 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
3501 DOOR_GFX_PAGEX7, 64,
3504 redraw_mask |= REDRAW_ALL;
3506 CloseDoor(DOOR_CLOSE_ALL);
3508 DrawCompleteVideoDisplay();
3510 if (setup.autorecord)
3511 TapeStartRecording();
3513 level_editor_test_game = TRUE;
3514 game_status = PLAYING;
3520 case ED_CTRL_ID_EXIT:
3521 for(y=0; y<lev_fieldy; y++)
3522 for(x=0; x<lev_fieldx; x++)
3523 if (Feld[x][y] != Ur[x][y])
3524 level_changed = TRUE;
3526 if (!level_changed ||
3527 Request("Level has changed! Exit without saving ?",
3528 REQ_ASK | REQ_STAY_OPEN))
3530 CloseDoor(DOOR_CLOSE_1);
3533 CloseDoor(DOOR_CLOSE_ALL);
3536 /* draw smaller door */
3537 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
3538 DOOR_GFX_PAGEX7, 64,
3541 redraw_mask |= REDRAW_ALL;
3543 game_status = MAINMENU;
3548 CloseDoor(DOOR_CLOSE_1);
3549 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
3550 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
3551 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3552 OpenDoor(DOOR_OPEN_1);
3558 if (gi->event.type == GD_EVENT_PRESSED)
3559 printf("default: HandleControlButtons: GD_EVENT_PRESSED\n");
3560 else if (gi->event.type == GD_EVENT_RELEASED)
3561 printf("default: HandleControlButtons: GD_EVENT_RELEASED\n");
3562 else if (gi->event.type == GD_EVENT_MOVING)
3563 printf("default: HandleControlButtons: GD_EVENT_MOVING\n");
3565 printf("default: HandleControlButtons: ?\n");
3571 void HandleLevelEditorKeyInput(KeySym key)
3573 if (edit_mode == ED_MODE_DRAWING)
3575 char letter = getCharFromKeySym(key);
3577 if (drawing_function == ED_CTRL_ID_TEXT)
3580 DrawLevelText(0, 0, letter, TEXT_WRITECHAR);
3581 else if (key == XK_Delete || key == XK_BackSpace)
3582 DrawLevelText(0, 0, 0, TEXT_BACKSPACE);
3583 else if (key == XK_Return)
3584 DrawLevelText(0, 0, 0, TEXT_NEWLINE);
3586 else if (button_status == MB_RELEASED)
3594 id = ED_CTRL_ID_SINGLE_ITEMS;
3597 id = ED_CTRL_ID_CONNECTED_ITEMS;
3600 id = ED_CTRL_ID_LINE;
3603 id = ED_CTRL_ID_TEXT;
3606 id = ED_CTRL_ID_RECTANGLE;
3609 id = ED_CTRL_ID_FILLED_BOX;
3612 id = ED_CTRL_ID_PROPERTIES;
3615 id = ED_CTRL_ID_FLOOD_FILL;
3618 id = ED_CTRL_ID_GRAB_BRUSH;
3621 id = ED_CTRL_ID_PICK_ELEMENT;
3625 id = ED_CTRL_ID_UNDO;
3628 id = ED_CTRL_ID_INFO;
3631 id = ED_CTRL_ID_SAVE;
3634 id = ED_CTRL_ID_CLEAR;
3637 id = ED_CTRL_ID_TEST;
3640 id = ED_CTRL_ID_EXIT;
3644 id = ED_CTRL_ID_NONE;
3648 if (id != ED_CTRL_ID_NONE)
3649 ClickOnGadget(level_editor_gadget[id]);
3655 id = ED_CTRL_ID_SCROLL_LEFT;
3658 id = ED_CTRL_ID_SCROLL_RIGHT;
3661 id = ED_CTRL_ID_SCROLL_UP;
3664 id = ED_CTRL_ID_SCROLL_DOWN;
3668 id = ED_CTRL_ID_NONE;
3672 if (id != ED_CTRL_ID_NONE)
3673 ClickOnGadget(level_editor_gadget[id]);
3679 static void HandleTextInputGadgets(struct GadgetInfo *gi)
3681 int id = gi->custom_id;
3685 case ED_CTRL_ID_LEVEL_NAME:
3686 strcpy(level.name, gi->text.value);
3694 /* values for ClearEditorGadgetInfoText() and HandleGadgetInfoText() */
3695 #define INFOTEXT_XPOS SX
3696 #define INFOTEXT_YPOS (SY + SYSIZE - MINI_TILEX + 2)
3697 #define INFOTEXT_XSIZE SXSIZE
3698 #define INFOTEXT_YSIZE MINI_TILEX
3699 #define MAX_INFOTEXT_LEN (SXSIZE / FONT2_XSIZE)
3701 void ClearEditorGadgetInfoText()
3703 XFillRectangle(display, drawto, gc,
3704 INFOTEXT_XPOS, INFOTEXT_YPOS, INFOTEXT_XSIZE, INFOTEXT_YSIZE);
3705 redraw_mask |= REDRAW_FIELD;
3708 void HandleEditorGadgetInfoText(void *ptr)
3710 struct GadgetInfo *gi = (struct GadgetInfo *)ptr;
3711 char infotext[MAX_INFOTEXT_LEN + 1];
3713 ClearEditorGadgetInfoText();
3715 /* misuse this function to delete brush cursor, if needed */
3716 if (edit_mode == ED_MODE_DRAWING && draw_with_brush)
3717 DeleteBrushFromCursor();
3719 if (gi == NULL || gi->description_text == NULL)
3722 strncpy(infotext, gi->description_text, MAX_INFOTEXT_LEN);
3723 infotext[MAX_INFOTEXT_LEN] = '\0';
3725 DrawText(INFOTEXT_XPOS, INFOTEXT_YPOS, infotext, FS_SMALL, FC_YELLOW);
3728 static void HandleDrawingAreaInfo(struct GadgetInfo *gi)
3730 static int start_lx, start_ly;
3732 int id = gi->custom_id;
3733 int sx = gi->event.x;
3734 int sy = gi->event.y;
3735 int lx = sx + level_xpos;
3736 int ly = sy + level_ypos;
3738 ClearEditorGadgetInfoText();
3740 if (id == ED_CTRL_ID_DRAWING_LEVEL)
3742 if (IN_LEV_FIELD(lx, ly))
3744 if (gi->state == GD_BUTTON_PRESSED)
3746 if (gi->event.type == GD_EVENT_PRESSED)
3752 switch (drawing_function)
3754 case ED_CTRL_ID_SINGLE_ITEMS:
3755 infotext = "Drawing single items";
3757 case ED_CTRL_ID_CONNECTED_ITEMS:
3758 infotext = "Drawing connected items";
3760 case ED_CTRL_ID_LINE:
3761 infotext = "Drawing line";
3763 case ED_CTRL_ID_TEXT:
3764 infotext = "Setting text cursor";
3766 case ED_CTRL_ID_RECTANGLE:
3767 infotext = "Drawing rectangle";
3769 case ED_CTRL_ID_FILLED_BOX:
3770 infotext = "Drawing filled box";
3772 case ED_CTRL_ID_FLOOD_FILL:
3773 infotext = "Flood fill";
3775 case ED_CTRL_ID_GRAB_BRUSH:
3776 infotext = "Grabbing brush";
3778 case ED_CTRL_ID_PICK_ELEMENT:
3779 infotext = "Picking element";
3783 infotext = "Drawing position";
3787 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
3788 "%s: %d, %d", infotext,
3789 ABS(lx - start_lx) + 1,
3790 ABS(ly - start_ly) + 1);
3793 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
3794 "Level position: %d, %d", lx, ly);
3797 /* misuse this function to draw brush cursor, if needed */
3798 if (edit_mode == ED_MODE_DRAWING && draw_with_brush)
3799 CopyBrushToCursor(sx, sy);
3801 else if (id == ED_CTRL_ID_AMOEBA_CONTENT)
3802 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
3805 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
3806 "Cruncher %d content: %d, %d", id - ED_CTRL_ID_ELEMCONT_0 + 1,