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_SINGLE_ITEMS 0
118 #define ED_CTRL_ID_CONNECTED_ITEMS 1
119 #define ED_CTRL_ID_LINE 2
120 #define ED_CTRL_ID_TEXT 3
121 #define ED_CTRL_ID_RECTANGLE 4
122 #define ED_CTRL_ID_FILLED_BOX 5
123 #define ED_CTRL_ID_WRAP_UP 6
124 #define ED_CTRL_ID_PROPERTIES 7
125 #define ED_CTRL_ID_FLOOD_FILL 8
126 #define ED_CTRL_ID_WRAP_LEFT 9
127 #define ED_CTRL_ID_UNUSED1 10
128 #define ED_CTRL_ID_WRAP_RIGHT 11
129 #define ED_CTRL_ID_RANDOM_PLACEMENT 12
130 #define ED_CTRL_ID_BRUSH 13
131 #define ED_CTRL_ID_WRAP_DOWN 14
132 #define ED_CTRL_ID_PICK_ELEMENT 15
133 #define ED_CTRL_ID_UNDO 16
134 #define ED_CTRL_ID_INFO 17
135 #define ED_CTRL_ID_SAVE 18
136 #define ED_CTRL_ID_CLEAR 19
137 #define ED_CTRL_ID_TEST 20
138 #define ED_CTRL_ID_EXIT 21
140 /* counter button identifiers */
141 #define ED_CTRL_ID_SCORE_DOWN 22
142 #define ED_CTRL_ID_SCORE_UP 23
143 #define ED_CTRL_ID_ELEMCONT_DOWN 24
144 #define ED_CTRL_ID_ELEMCONT_UP 25
146 /* drawing area identifiers */
147 #define ED_CTRL_ID_DRAWING_LEVEL 26
148 #define ED_CTRL_ID_ELEMCONT_0 27
149 #define ED_CTRL_ID_ELEMCONT_7 34
150 #define ED_CTRL_ID_AMOEBA_CONTENT 35
152 /* text input identifiers */
153 #define ED_CTRL_ID_LEVEL_NAME 36
155 /* gadgets for scrolling of drawing area */
156 #define ED_CTRL_ID_SCROLL_UP 37
157 #define ED_CTRL_ID_SCROLL_DOWN 38
158 #define ED_CTRL_ID_SCROLL_LEFT 39
159 #define ED_CTRL_ID_SCROLL_RIGHT 40
160 #define ED_CTRL_ID_SCROLL_VERTICAL 41
161 #define ED_CTRL_ID_SCROLL_HORIZONTAL 42
163 #define ED_NUM_GADGETS 43
165 /* values for counter gadgets */
166 #define ED_COUNTER_SCORE 0
167 #define ED_COUNTER_ELEMCONT 1
169 #define ED_NUM_COUNTERBUTTONS 2
170 #define ED_NUM_SCROLLBUTTONS 4
171 #define ED_NUM_SCROLLBARS 2
173 /* values for CopyLevelToUndoBuffer() */
174 #define UNDO_IMMEDIATE 0
175 #define UNDO_ACCUMULATE 1
177 static char *control_infotext[ED_NUM_CTRL_BUTTONS] =
180 "draw connected items",
182 "enter text elements",
183 "draw outline rectangles",
185 "wrap (rotate) level up",
186 "properties of drawing element",
188 "wrap (rotate) level left",
190 "wrap (rotate) level right",
191 "random element placement",
193 "wrap (rotate) level down",
194 "pick drawing element from editing area",
195 "undo last operation",
207 } counterbutton_info[ED_NUM_COUNTERBUTTONS] =
209 { ED_COUNT_SCORE_XPOS, ED_COUNT_SCORE_YPOS, ED_CTRL_ID_SCORE_DOWN },
210 { ED_COUNT_ELEMCONT_XPOS, ED_COUNT_ELEMCONT_YPOS, ED_CTRL_ID_ELEMCONT_DOWN }
219 } scrollbutton_info[ED_NUM_SCROLLBUTTONS] =
222 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 0 * ED_SCROLLBUTTON_YSIZE,
223 ED_SCROLL_UP_XPOS, ED_SCROLL_UP_YPOS, ED_CTRL_ID_SCROLL_UP,
224 "scroll level editing area up"
227 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 1 * ED_SCROLLBUTTON_YSIZE,
228 ED_SCROLL_DOWN_XPOS, ED_SCROLL_DOWN_YPOS, ED_CTRL_ID_SCROLL_DOWN,
229 "scroll level editing area down"
232 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 2 * ED_SCROLLBUTTON_YSIZE,
233 ED_SCROLL_LEFT_XPOS, ED_SCROLL_LEFT_YPOS, ED_CTRL_ID_SCROLL_LEFT,
234 "scroll level editing area left"
237 ED_SCROLLBUTTON_XPOS, ED_SCROLLBUTTON_YPOS + 3 * ED_SCROLLBUTTON_YSIZE,
238 ED_SCROLL_RIGHT_XPOS, ED_SCROLL_RIGHT_YPOS, ED_CTRL_ID_SCROLL_RIGHT,
239 "scroll level editing area right"
251 } scrollbar_info[ED_NUM_SCROLLBARS] =
254 ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS,
255 ED_SCROLL_VERTICAL_XPOS, ED_SCROLL_VERTICAL_YPOS,
256 ED_SCROLL_VERTICAL_XSIZE, ED_SCROLL_VERTICAL_YSIZE,
257 GD_TYPE_SCROLLBAR_VERTICAL,
258 ED_CTRL_ID_SCROLL_VERTICAL,
259 "scroll level editing area vertically"
262 ED_SCROLLBAR_XPOS, ED_SCROLLBAR_YPOS,
263 ED_SCROLL_HORIZONTAL_XPOS, ED_SCROLL_HORIZONTAL_YPOS,
264 ED_SCROLL_HORIZONTAL_XSIZE, ED_SCROLL_HORIZONTAL_YSIZE,
265 GD_TYPE_SCROLLBAR_HORIZONTAL,
266 ED_CTRL_ID_SCROLL_HORIZONTAL,
267 "scroll level editing area horizontally"
272 /* forward declaration for internal use */
273 static void DrawDrawingWindow();
274 static void DrawPropertiesWindow();
275 static void CopyLevelToUndoBuffer(int);
276 static void HandleControlButtons(struct GadgetInfo *);
277 static void HandleCounterButtons(struct GadgetInfo *);
278 static void HandleDrawingAreas(struct GadgetInfo *);
279 static void HandleDrawingAreaInfo(struct GadgetInfo *);
280 static void HandleTextInputGadgets(struct GadgetInfo *);
282 static struct GadgetInfo *level_editor_gadget[ED_NUM_GADGETS];
283 static boolean level_editor_gadgets_created = FALSE;
285 static int drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
286 static int last_drawing_function = ED_CTRL_ID_SINGLE_ITEMS;
287 static boolean draw_with_brush = FALSE;
288 static int properties_element = 0;
290 static short ElementContent[MAX_ELEMCONT][3][3];
291 static short FieldBackup[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
292 static short UndoBuffer[NUM_UNDO_STEPS][MAX_LEV_FIELDX][MAX_LEV_FIELDY];
293 static int undo_buffer_position = 0;
294 static int undo_buffer_steps = 0;
296 static int random_placement_percentage = 10;
297 static int random_placement_num_objects = 10;
299 static int random_placement_method = RANDOM_USE_PERCENTAGE;
301 static int random_placement_method = RANDOM_USE_NUM_OBJECTS;
304 /* pointer to score value */
305 static int *gadget_score_value;
306 static int *gadget_areas_value;
308 static int level_xpos,level_ypos;
309 static int edit_mode;
310 static boolean name_typing;
311 static int new_element1 = EL_MAUERWERK;
312 static int new_element2 = EL_LEERRAUM;
313 static int new_element3 = EL_ERDREICH;
315 int element_shift = 0;
317 int editor_element[] =
319 EL_CHAR_A + ('B' - 'A'),
320 EL_CHAR_A + ('O' - 'A'),
321 EL_CHAR_A + ('U' - 'A'),
322 EL_CHAR_A + ('L' - 'A'),
325 EL_CHAR_A + ('D' - 'A'),
326 EL_CHAR_A + ('E' - 'A'),
327 EL_CHAR_A + ('R' - 'A'),
329 EL_CHAR_A + ('D' - 'A'),
330 EL_CHAR_A + ('A' - 'A'),
331 EL_CHAR_A + ('S' - 'A'),
332 EL_CHAR_A + ('H' - 'A'),
359 EL_CHAR_A + ('E' - 'A'),
360 EL_CHAR_A + ('M' - 'A'),
361 EL_CHAR_A + ('E' - 'A'),
364 EL_CHAR_A + ('R' - 'A'),
365 EL_CHAR_A + ('A' - 'A'),
366 EL_CHAR_A + ('L' - 'A'),
367 EL_CHAR_A + ('D' - 'A'),
369 EL_CHAR_A + ('M' - 'A'),
370 EL_CHAR_A + ('I' - 'A'),
371 EL_CHAR_A + ('N' - 'A'),
372 EL_CHAR_A + ('E' - 'A'),
449 EL_CHAR_A + ('M' - 'A'),
450 EL_CHAR_A + ('O' - 'A'),
451 EL_CHAR_A + ('R' - 'A'),
452 EL_CHAR_A + ('E' - 'A'),
504 EL_CHAR_A + ('S' - 'A'),
505 EL_CHAR_A + ('O' - 'A'),
506 EL_CHAR_A + ('K' - 'A'),
507 EL_CHAR_A + ('O' - 'A'),
510 EL_CHAR_A + ('B' - 'A'),
511 EL_CHAR_A + ('A' - 'A'),
512 EL_CHAR_A + ('N' - 'A'),
515 EL_SOKOBAN_FELD_LEER,
516 EL_SOKOBAN_FELD_VOLL,
585 EL_CHAR_A + ('D' - 'A'),
586 EL_CHAR_A + ('Y' - 'A'),
587 EL_CHAR_A + ('N' - 'A'),
588 EL_CHAR_A + ('A' - 'A'),
590 EL_CHAR_A + ('B' - 'A'),
591 EL_CHAR_A + ('L' - 'A'),
592 EL_CHAR_A + ('A' - 'A'),
593 EL_CHAR_A + ('S' - 'A'),
596 EL_CHAR_A + ('T' - 'A'),
597 EL_CHAR_A + ('E' - 'A'),
598 EL_CHAR_A + ('R' - 'A'),
681 int elements_in_list = sizeof(editor_element)/sizeof(int);
683 static void ScrollMiniLevel(int from_x, int from_y, int scroll)
686 int dx = (scroll == ED_SCROLL_LEFT ? -1 : scroll == ED_SCROLL_RIGHT ? 1 : 0);
687 int dy = (scroll == ED_SCROLL_UP ? -1 : scroll == ED_SCROLL_DOWN ? 1 : 0);
689 XCopyArea(display, drawto, drawto, gc,
690 SX + (dx == -1 ? MINI_TILEX : 0),
691 SY + (dy == -1 ? MINI_TILEY : 0),
692 (ED_FIELDX * MINI_TILEX) - (dx != 0 ? MINI_TILEX : 0),
693 (ED_FIELDY * MINI_TILEY) - (dy != 0 ? MINI_TILEY : 0),
694 SX + (dx == +1 ? MINI_TILEX : 0),
695 SY + (dy == +1 ? MINI_TILEY : 0));
698 x = (dx == 1 ? 0 : ED_FIELDX - 1);
699 for(y=0; y<ED_FIELDY; y++)
700 DrawMiniElementOrWall(x, y, from_x, from_y);
704 y = (dy == 1 ? 0 : ED_FIELDY - 1);
705 for(x=0; x<ED_FIELDX; x++)
706 DrawMiniElementOrWall(x, y, from_x, from_y);
709 redraw_mask |= REDRAW_FIELD;
713 void InitLevelEditorGadgets()
717 for (i=0; i<ED_NUM_GADGETS; i++)
718 level_editor_gadget[i] = NULL;
721 static void CreateControlButtons()
723 Pixmap gd_pixmap = pix[PIX_DOOR];
724 struct GadgetInfo *gi;
725 unsigned long event_mask;
728 /* create toolbox buttons */
729 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
733 int gd_xoffset, gd_yoffset;
734 int gd_x1, gd_x2, gd_y1, gd_y2;
737 boolean radio_button_pressed;
739 if (id == ED_CTRL_ID_SINGLE_ITEMS ||
740 id == ED_CTRL_ID_CONNECTED_ITEMS ||
741 id == ED_CTRL_ID_LINE ||
742 id == ED_CTRL_ID_TEXT ||
743 id == ED_CTRL_ID_RECTANGLE ||
744 id == ED_CTRL_ID_FILLED_BOX ||
745 id == ED_CTRL_ID_FLOOD_FILL ||
746 id == ED_CTRL_ID_BRUSH ||
747 id == ED_CTRL_ID_PICK_ELEMENT)
749 button_type = GD_TYPE_RADIO_BUTTON;
751 radio_button_pressed = (id == drawing_function ? TRUE : FALSE);
752 event_mask = GD_EVENT_PRESSED;
756 button_type = GD_TYPE_NORMAL_BUTTON;
758 radio_button_pressed = FALSE;
760 if (id == ED_CTRL_ID_WRAP_LEFT ||
761 id == ED_CTRL_ID_WRAP_RIGHT ||
762 id == ED_CTRL_ID_WRAP_UP ||
763 id == ED_CTRL_ID_WRAP_DOWN)
764 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
766 event_mask = GD_EVENT_RELEASED;
769 if (id < ED_NUM_CTRL1_BUTTONS)
771 int x = i % ED_CTRL1_BUTTONS_HORIZ;
772 int y = i / ED_CTRL1_BUTTONS_HORIZ;
774 gd_xoffset = ED_CTRL1_BUTTONS_XPOS + x * ED_CTRL1_BUTTON_XSIZE;
775 gd_yoffset = ED_CTRL1_BUTTONS_YPOS + y * ED_CTRL1_BUTTON_YSIZE;
776 width = ED_CTRL1_BUTTON_XSIZE;
777 height = ED_CTRL1_BUTTON_YSIZE;
781 int x = (i - ED_NUM_CTRL1_BUTTONS) % ED_CTRL2_BUTTONS_HORIZ;
782 int y = (i - ED_NUM_CTRL1_BUTTONS) / ED_CTRL2_BUTTONS_HORIZ;
784 gd_xoffset = ED_CTRL2_BUTTONS_XPOS + x * ED_CTRL2_BUTTON_XSIZE;
785 gd_yoffset = ED_CTRL2_BUTTONS_YPOS + y * ED_CTRL2_BUTTON_YSIZE;
786 width = ED_CTRL2_BUTTON_XSIZE;
787 height = ED_CTRL2_BUTTON_YSIZE;
790 gd_x1 = DOOR_GFX_PAGEX8 + gd_xoffset;
791 gd_x2 = DOOR_GFX_PAGEX7 + gd_xoffset;
792 gd_y1 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_GFX_YPOS + gd_yoffset;
793 gd_y2 = DOOR_GFX_PAGEY1 + ED_CTRL_BUTTONS_ALT_GFX_YPOS + gd_yoffset;
795 gi = CreateGadget(GDI_CUSTOM_ID, id,
796 GDI_DESCRIPTION_TEXT, control_infotext[i],
797 GDI_X, EX + gd_xoffset,
798 GDI_Y, EY + gd_yoffset,
801 GDI_TYPE, button_type,
802 GDI_STATE, GD_BUTTON_UNPRESSED,
803 GDI_RADIO_NR, radio_button_nr,
804 GDI_RADIO_PRESSED, radio_button_pressed,
805 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
806 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y1,
807 GDI_ALT_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y2,
808 GDI_ALT_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
809 GDI_EVENT_MASK, event_mask,
810 GDI_CALLBACK_ACTION, HandleControlButtons,
814 Error(ERR_EXIT, "cannot create gadget");
816 level_editor_gadget[id] = gi;
819 /* create buttons for scrolling of drawing area */
820 for (i=0; i<ED_NUM_SCROLLBUTTONS; i++)
822 int id = scrollbutton_info[i].gadget_id;
823 int gd_x1, gd_x2, gd_y;
825 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
827 gd_y = DOOR_GFX_PAGEY1 + scrollbutton_info[i].ypos;
828 gd_x1 = DOOR_GFX_PAGEX8 + scrollbutton_info[i].xpos;
829 gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
831 gi = CreateGadget(GDI_CUSTOM_ID, id,
832 GDI_DESCRIPTION_TEXT, scrollbutton_info[i].text,
833 GDI_X, SX + scrollbutton_info[i].x,
834 GDI_Y, SY + scrollbutton_info[i].y,
835 GDI_WIDTH, ED_SCROLLBUTTON_XSIZE,
836 GDI_HEIGHT, ED_SCROLLBUTTON_YSIZE,
837 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
838 GDI_STATE, GD_BUTTON_UNPRESSED,
839 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
840 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
841 GDI_EVENT_MASK, event_mask,
842 GDI_CALLBACK_ACTION, HandleControlButtons,
846 Error(ERR_EXIT, "cannot create gadget");
848 level_editor_gadget[id] = gi;
852 static void CreateCounterButtons()
856 for (i=0; i<ED_NUM_COUNTERBUTTONS; i++)
860 Pixmap gd_pixmap = pix[PIX_DOOR];
861 struct GadgetInfo *gi;
862 int id = counterbutton_info[i].gadget_id + j;
864 int gd_x1, gd_x2, gd_y;
865 unsigned long event_mask;
867 event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED;
869 gd_xoffset = (j == 0 ? ED_BUTTON_MINUS_XPOS : ED_BUTTON_PLUS_XPOS);
870 gd_x1 = DOOR_GFX_PAGEX4 + gd_xoffset;
871 gd_x2 = DOOR_GFX_PAGEX3 + gd_xoffset;
872 gd_y = DOOR_GFX_PAGEY1 + ED_BUTTON_COUNT_YPOS;
874 gi = CreateGadget(GDI_CUSTOM_ID, id,
875 GDI_X, SX + counterbutton_info[i].x + gd_xoffset,
876 GDI_Y, SY + counterbutton_info[i].y,
877 GDI_WIDTH, ED_BUTTON_COUNT_XSIZE,
878 GDI_HEIGHT, ED_BUTTON_COUNT_YSIZE,
879 GDI_TYPE, GD_TYPE_NORMAL_BUTTON,
880 GDI_STATE, GD_BUTTON_UNPRESSED,
881 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y,
882 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y,
883 GDI_EVENT_MASK, event_mask,
884 GDI_CALLBACK_ACTION, HandleCounterButtons,
888 Error(ERR_EXIT, "cannot create gadget");
890 level_editor_gadget[id] = gi;
895 static void CreateDrawingAreas()
897 struct GadgetInfo *gi;
898 unsigned long event_mask;
903 GD_EVENT_PRESSED | GD_EVENT_RELEASED | GD_EVENT_MOVING |
904 GD_EVENT_OFF_BORDERS;
906 /* one for the level drawing area ... */
907 id = ED_CTRL_ID_DRAWING_LEVEL;
908 gi = CreateGadget(GDI_CUSTOM_ID, id,
911 GDI_TYPE, GD_TYPE_DRAWING_AREA,
912 GDI_AREA_SIZE, ED_FIELDX, ED_FIELDY,
913 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
914 GDI_EVENT_MASK, event_mask,
915 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
916 GDI_CALLBACK_ACTION, HandleDrawingAreas,
920 Error(ERR_EXIT, "cannot create gadget");
922 level_editor_gadget[id] = gi;
924 /* ... up to eight areas for element content ... */
925 for (i=0; i<MAX_ELEMCONT; i++)
927 int gx = SX + ED_AREA_ELEMCONT_XPOS + 5 * (i % 4) * MINI_TILEX;
928 int gy = SX + ED_AREA_ELEMCONT_YPOS + 6 * (i / 4) * MINI_TILEY;
930 id = ED_CTRL_ID_ELEMCONT_0 + i;
931 gi = CreateGadget(GDI_CUSTOM_ID, id,
934 GDI_WIDTH, 3 * MINI_TILEX,
935 GDI_HEIGHT, 3 * MINI_TILEY,
936 GDI_TYPE, GD_TYPE_DRAWING_AREA,
937 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
938 GDI_EVENT_MASK, event_mask,
939 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
940 GDI_CALLBACK_ACTION, HandleDrawingAreas,
944 Error(ERR_EXIT, "cannot create gadget");
946 level_editor_gadget[id] = gi;
949 /* ... and one for the amoeba content */
950 id = ED_CTRL_ID_AMOEBA_CONTENT;
951 gi = CreateGadget(GDI_CUSTOM_ID, id,
952 GDI_X, SX + ED_AREA_ELEMCONT_XPOS,
953 GDI_Y, SY + ED_AREA_ELEMCONT_YPOS,
954 GDI_WIDTH, MINI_TILEX,
955 GDI_HEIGHT, MINI_TILEY,
956 GDI_TYPE, GD_TYPE_DRAWING_AREA,
957 GDI_ITEM_SIZE, MINI_TILEX, MINI_TILEY,
958 GDI_EVENT_MASK, event_mask,
959 GDI_CALLBACK_INFO, HandleDrawingAreaInfo,
960 GDI_CALLBACK_ACTION, HandleDrawingAreas,
964 Error(ERR_EXIT, "cannot create gadget");
966 level_editor_gadget[id] = gi;
969 static void CreateTextInputGadgets()
971 Pixmap gd_pixmap = pix[PIX_DOOR];
973 struct GadgetInfo *gi;
974 unsigned long event_mask;
977 gd_x = DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS;
978 gd_y = DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS;
979 event_mask = GD_EVENT_TEXT_RETURN | GD_EVENT_TEXT_LEAVING;
981 /* text input gadget for the level name */
982 id = ED_CTRL_ID_LEVEL_NAME;
983 gi = CreateGadget(GDI_CUSTOM_ID, id,
984 GDI_X, SX + ED_COUNT_ELEMCONT_XPOS,
985 GDI_Y, SY + ED_AREA_ELEMCONT_YPOS + 3 * TILEX,
986 GDI_TYPE, GD_TYPE_TEXTINPUT,
987 GDI_TEXT_VALUE, level.name,
989 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x, gd_y,
990 GDI_DESIGN_PRESSED, gd_pixmap, gd_x, gd_y,
991 GDI_DESIGN_BORDER, 3,
992 GDI_EVENT_MASK, event_mask,
993 GDI_CALLBACK_ACTION, HandleTextInputGadgets,
997 Error(ERR_EXIT, "cannot create gadget");
999 level_editor_gadget[id] = gi;
1002 static void CreateScrollbarGadgets()
1006 for (i=0; i<ED_NUM_SCROLLBARS; i++)
1008 int id = scrollbar_info[i].gadget_id;
1009 Pixmap gd_pixmap = pix[PIX_DOOR];
1010 int gd_x1, gd_x2, gd_y1, gd_y2;
1011 struct GadgetInfo *gi;
1012 int items_max, items_visible, item_position;
1013 unsigned long event_mask;
1015 if (scrollbar_info[i].type == GD_TYPE_SCROLLBAR_HORIZONTAL)
1017 items_max = lev_fieldx + 2;
1018 items_visible = ED_FIELDX;
1023 items_max = lev_fieldy + 2;
1024 items_visible = ED_FIELDY;
1028 event_mask = GD_EVENT_MOVING | GD_EVENT_OFF_BORDERS;
1030 gd_x1 = DOOR_GFX_PAGEX8 + scrollbar_info[i].xpos;
1031 gd_x2 = gd_x1 - ED_SCROLLBUTTON_XSIZE;
1032 gd_y1 = DOOR_GFX_PAGEY1 + scrollbar_info[i].ypos;
1033 gd_y2 = DOOR_GFX_PAGEY1 + scrollbar_info[i].ypos;
1035 gi = CreateGadget(GDI_CUSTOM_ID, id,
1036 GDI_DESCRIPTION_TEXT, scrollbar_info[i].text,
1037 GDI_X, SX + scrollbar_info[i].x,
1038 GDI_Y, SY + scrollbar_info[i].y,
1039 GDI_WIDTH, scrollbar_info[i].width,
1040 GDI_HEIGHT, scrollbar_info[i].height,
1041 GDI_TYPE, scrollbar_info[i].type,
1042 GDI_SCROLLBAR_ITEMS_MAX, items_max,
1043 GDI_SCROLLBAR_ITEMS_VISIBLE, items_visible,
1044 GDI_SCROLLBAR_ITEM_POSITION, item_position,
1045 GDI_STATE, GD_BUTTON_UNPRESSED,
1046 GDI_DESIGN_UNPRESSED, gd_pixmap, gd_x1, gd_y1,
1047 GDI_DESIGN_PRESSED, gd_pixmap, gd_x2, gd_y2,
1048 GDI_DESIGN_BORDER, 3,
1049 GDI_EVENT_MASK, event_mask,
1050 GDI_CALLBACK_ACTION, HandleControlButtons,
1054 Error(ERR_EXIT, "cannot create gadget");
1056 level_editor_gadget[id] = gi;
1060 static void CreateLevelEditorGadgets()
1062 if (level_editor_gadgets_created)
1065 CreateControlButtons();
1066 CreateCounterButtons();
1067 CreateDrawingAreas();
1068 CreateTextInputGadgets();
1069 CreateScrollbarGadgets();
1071 level_editor_gadgets_created = TRUE;
1074 static void MapControlButtons()
1078 for (i=0; i<ED_NUM_CTRL_BUTTONS; i++)
1079 MapGadget(level_editor_gadget[i]);
1082 static void MapCounterButtons(int id)
1087 MapGadget(level_editor_gadget[counterbutton_info[id].gadget_id + i]);
1090 static void MapDrawingArea(int id)
1092 MapGadget(level_editor_gadget[id]);
1095 static void MapTextInputGadget(int id)
1097 MapGadget(level_editor_gadget[id]);
1100 static void MapMainDrawingArea()
1104 for (i=0; i<ED_NUM_SCROLLBUTTONS; i++)
1105 MapGadget(level_editor_gadget[scrollbutton_info[i].gadget_id]);
1107 for (i=0; i<ED_NUM_SCROLLBARS; i++)
1108 MapGadget(level_editor_gadget[scrollbar_info[i].gadget_id]);
1110 MapDrawingArea(ED_CTRL_ID_DRAWING_LEVEL);
1113 static void UnmapDrawingArea(int id)
1115 UnmapGadget(level_editor_gadget[id]);
1118 void UnmapLevelEditorWindowGadgets()
1122 for (i=ED_NUM_CTRL_BUTTONS; i<ED_NUM_GADGETS; i++)
1123 UnmapGadget(level_editor_gadget[i]);
1126 void UnmapLevelEditorGadgets()
1130 for (i=0; i<ED_NUM_GADGETS; i++)
1131 UnmapGadget(level_editor_gadget[i]);
1136 int i, x, y, graphic;
1140 edit_mode = ED_MODE_DRAWING;
1141 name_typing = FALSE;
1143 CloseDoor(DOOR_CLOSE_ALL);
1145 OpenDoor(DOOR_OPEN_2 | DOOR_NO_DELAY);
1147 if (level_editor_test_game)
1149 for(x=0; x<lev_fieldx; x++)
1150 for(y=0; y<lev_fieldy; y++)
1151 Feld[x][y] = Ur[x][y];
1153 for(x=0; x<lev_fieldx; x++)
1154 for(y=0; y<lev_fieldy; y++)
1155 Ur[x][y] = FieldBackup[x][y];
1157 level_editor_test_game = FALSE;
1161 undo_buffer_position = -1;
1162 undo_buffer_steps = -1;
1163 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
1167 DrawMiniLevel(level_xpos, level_ypos);
1171 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1172 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY1,
1174 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
1175 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1176 DOOR_GFX_PAGEX6+ED_BUTTON_ELEM_XPOS,
1177 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS,
1178 4*ED_BUTTON_ELEM_XSIZE,5*ED_BUTTON_ELEM_YSIZE,
1179 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS,
1180 DOOR_GFX_PAGEY1+ED_BUTTON_EUP_Y2POS);
1182 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1184 if (i < elements_in_list)
1185 graphic = el2gfx(editor_element[i + element_shift]);
1187 graphic = GFX_LEERRAUM;
1189 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1190 DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS+3 +
1191 (i%MAX_ELEM_X)*ED_BUTTON_ELEM_XSIZE,
1192 DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS+3 +
1193 (i/MAX_ELEM_X)*ED_BUTTON_ELEM_YSIZE,
1197 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1198 DOOR_GFX_PAGEX1+ED_WIN_MB_LEFT_XPOS,
1199 DOOR_GFX_PAGEY1+ED_WIN_MB_LEFT_YPOS,
1200 el2gfx(new_element1));
1201 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1202 DOOR_GFX_PAGEX1+ED_WIN_MB_MIDDLE_XPOS,
1203 DOOR_GFX_PAGEY1+ED_WIN_MB_MIDDLE_YPOS,
1204 el2gfx(new_element2));
1205 DrawMiniGraphicExt(pix[PIX_DB_DOOR],gc,
1206 DOOR_GFX_PAGEX1+ED_WIN_MB_RIGHT_XPOS,
1207 DOOR_GFX_PAGEY1+ED_WIN_MB_RIGHT_YPOS,
1208 el2gfx(new_element3));
1209 DrawTextExt(pix[PIX_DB_DOOR],gc,
1210 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS,
1211 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1212 int2str(level_nr,2),FS_SMALL,FC_SPECIAL1);
1213 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1214 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+3,
1215 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1217 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS,
1218 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
1219 XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
1220 DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+14,
1221 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
1223 DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS+9,
1224 DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
1226 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1227 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1229 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1231 /* draw bigger door */
1232 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1237 /* draw new control window */
1238 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
1239 DOOR_GFX_PAGEX8, 236,
1243 redraw_mask |= REDRAW_ALL;
1245 OpenDoor(DOOR_OPEN_1);
1247 if (!level_editor_gadgets_created)
1248 CreateLevelEditorGadgets();
1250 MapControlButtons();
1253 MapMainDrawingArea();
1256 DrawDrawingWindow();
1260 OpenDoor(DOOR_OPEN_1 | DOOR_OPEN_2);
1264 void DrawControlWindow()
1269 UnmapLevelEditorWindowGadgets();
1271 /* Inhalt der Mampfer */
1272 DrawText(ED_COUNT_GADGET_XPOS+1,SY+6,
1273 "Contents of a smashed cruncher:",FS_SMALL,FC_YELLOW);
1274 for(i=0;i<4;i++) for(y=0;y<4;y++) for(x=0;x<4;x++)
1276 DrawMiniElement(1+5*i+x,2+y,EL_ERDREICH);
1277 XFillRectangle(display,drawto,gc,
1278 SX+(1+5*i)*MINI_TILEX+MINI_TILEX/2-1,
1279 SY+(2)*MINI_TILEY+MINI_TILEY/2-1,
1280 3*MINI_TILEX+2,3*MINI_TILEY+2);
1282 XCopyArea(display,drawto,drawto,gc,
1283 SX+1*MINI_TILEX,SY+2*MINI_TILEY,
1284 4*5*MINI_TILEX,5*MINI_TILEY,
1285 SX+1*MINI_TILEX-MINI_TILEX/2,SY+2*MINI_TILEY-MINI_TILEY/2);
1288 for(y=0;y<3;y++) for(x=0;x<3;x++)
1289 DrawMiniElement(1+5*i+x,2+y,level.mampfer_inhalt[i][x][y]);
1291 DrawText(SX+MINI_TILEX+(5*i+1)*MINI_TILEX+1,
1292 SY+2*MINI_TILEY+(4)*MINI_TILEY-4,
1293 int2str(i+1,1),FS_SMALL,FC_YELLOW);
1296 /* Inhalt der Amöbe */
1297 for(y=0;y<2;y++) for(x=0;x<2;x++)
1299 DrawMiniElement(29+x,26+y,EL_ERDREICH);
1300 XFillRectangle(display,drawto,gc,
1301 SX+29*MINI_TILEX+MINI_TILEX/2-1,
1302 SY+26*MINI_TILEY+MINI_TILEY/2-1,
1303 MINI_TILEX+2,MINI_TILEY+2);
1305 XCopyArea(display,drawto,drawto,gc,
1306 SX+29*MINI_TILEX,SY+26*MINI_TILEY,
1307 3*MINI_TILEX,3*MINI_TILEY,
1308 SX+29*MINI_TILEX-MINI_TILEX/2,SY+26*MINI_TILEY-MINI_TILEY/2);
1309 DrawMiniElement(29,26,level.amoebe_inhalt);
1311 for(i=0;i<11+3+2;i++)
1313 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1314 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1315 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1316 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1317 ED_COUNT_GADGET_XPOS,
1318 ED_COUNT_GADGET_YPOS+i*ED_COUNT_GADGET_YSIZE);
1321 DrawText(ED_COUNT_VALUE_XPOS,
1322 ED_COUNT_VALUE_YPOS+i*ED_COUNT_GADGET_YSIZE,
1323 int2str(level.score[i],3),FS_SMALL,FC_YELLOW);
1325 DrawText(ED_COUNT_VALUE_XPOS,
1326 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1327 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1329 DrawText(ED_COUNT_VALUE_XPOS,
1330 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1331 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1333 DrawText(ED_COUNT_VALUE_XPOS,
1334 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1335 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1337 DrawText(ED_COUNT_VALUE_XPOS,
1338 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1339 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1341 DrawText(ED_COUNT_VALUE_XPOS,
1342 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1343 int2str(level.time,3),FS_SMALL,FC_YELLOW);
1346 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+0*ED_COUNT_TEXT_YSIZE,
1347 "Score for Emerald",FS_SMALL,FC_YELLOW);
1348 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+1*ED_COUNT_TEXT_YSIZE,
1349 "Score for Diamond",FS_SMALL,FC_YELLOW);
1350 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+2*ED_COUNT_TEXT_YSIZE,
1351 "Score for smashing a Bug",FS_SMALL,FC_YELLOW);
1352 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+3*ED_COUNT_TEXT_YSIZE,
1353 "Score for smashing a Spaceship",FS_SMALL,FC_YELLOW);
1354 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+4*ED_COUNT_TEXT_YSIZE,
1355 "Score for smashing a Cruncher",FS_SMALL,FC_YELLOW);
1356 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+5*ED_COUNT_TEXT_YSIZE,
1357 "Score for smashing an Alien",FS_SMALL,FC_YELLOW);
1358 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+6*ED_COUNT_TEXT_YSIZE,
1359 "Score for smashing a Pacman",FS_SMALL,FC_YELLOW);
1360 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+7*ED_COUNT_TEXT_YSIZE,
1361 "Score for cracking a nut",FS_SMALL,FC_YELLOW);
1362 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+8*ED_COUNT_TEXT_YSIZE,
1363 "Score for dynamite",FS_SMALL,FC_YELLOW);
1364 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+9*ED_COUNT_TEXT_YSIZE,
1365 "Score for key",FS_SMALL,FC_YELLOW);
1366 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+10*ED_COUNT_TEXT_YSIZE,
1367 "Score for each 10 seconds left",FS_SMALL,FC_YELLOW);
1368 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+11*ED_COUNT_TEXT_YSIZE,
1369 "Speed of the amoeba / Content",FS_SMALL,FC_YELLOW);
1370 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+12*ED_COUNT_TEXT_YSIZE,
1371 "Time for magic wall",FS_SMALL,FC_YELLOW);
1372 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+13*ED_COUNT_TEXT_YSIZE,
1373 "Time for wheel",FS_SMALL,FC_YELLOW);
1374 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+14*ED_COUNT_TEXT_YSIZE,
1375 "Emeralds needed in this level",FS_SMALL,FC_YELLOW);
1376 DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+15*ED_COUNT_TEXT_YSIZE,
1377 "Time available for this level",FS_SMALL,FC_YELLOW);
1379 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1380 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS,
1381 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1382 ED_WIN_COUNT_XSIZE,ED_WIN_COUNT_YSIZE,
1383 ED_COUNT_GADGET_XPOS,
1384 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1386 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1387 DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS+3+2*FONT2_XSIZE,
1388 DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
1389 ED_WIN_COUNT_XSIZE-3-2*FONT2_XSIZE,ED_WIN_COUNT_YSIZE,
1390 ED_COUNT_GADGET_XPOS+3+i*FONT2_XSIZE,
1391 ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
1392 DrawText(ED_COUNT_GADGET_XPOS+5,
1393 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1394 level.name,FS_SMALL,FC_YELLOW);
1395 DrawText(ED_COUNT_GADGET_XPOS+(30+3)*FONT2_XSIZE-5,
1396 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1397 "Title",FS_SMALL,FC_YELLOW);
1399 DrawText(ED_SIZE_GADGET_XPOS,ED_SIZE_GADGET_YPOS-18,
1400 "Playfield size:",FS_SMALL,FC_YELLOW);
1401 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1402 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1403 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1404 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1405 ED_SIZE_GADGET_XPOS,
1406 ED_SIZE_GADGET_YPOS+0*ED_COUNT_GADGET_YSIZE);
1407 XCopyArea(display,pix[PIX_DOOR],drawto,gc,
1408 DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
1409 DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
1410 DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
1411 ED_SIZE_GADGET_XPOS,
1412 ED_SIZE_GADGET_YPOS+1*ED_COUNT_GADGET_YSIZE);
1413 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+0*ED_SIZE_TEXT_YSIZE,
1414 "Width",FS_SMALL,FC_YELLOW);
1415 DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+1*ED_SIZE_TEXT_YSIZE,
1416 "Height",FS_SMALL,FC_YELLOW);
1417 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1418 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1419 DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1420 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1423 void AdjustLevelScrollPosition()
1425 if (level_xpos < -1)
1427 if (level_xpos > lev_fieldx - ED_FIELDX + 1)
1428 level_xpos = lev_fieldx - ED_FIELDX + 1;
1429 if (lev_fieldx < ED_FIELDX - 2)
1432 if (level_ypos < -1)
1434 if (level_ypos > lev_fieldy - ED_FIELDY + 1)
1435 level_ypos = lev_fieldy - ED_FIELDY + 1;
1436 if (lev_fieldy < ED_FIELDY - 2)
1440 void AdjustEditorScrollbar(int id)
1442 struct GadgetInfo *gi = level_editor_gadget[id];
1443 struct GadgetScrollbar *gs = &gi->scrollbar;
1444 int items_max, items_visible, item_position = gs->item_position;
1446 if (id == ED_CTRL_ID_SCROLL_HORIZONTAL)
1448 items_max = lev_fieldx + 2;
1449 items_visible = ED_FIELDX;
1453 items_max = lev_fieldy + 2;
1454 items_visible = ED_FIELDY;
1457 if (item_position > items_max - items_visible)
1458 item_position = items_max - items_visible;
1460 AdjustScrollbar(gi, items_max, item_position);
1463 static void PickDrawingElement(int button, int element)
1465 if (button < 1 || button > 3)
1470 new_element1 = element;
1471 DrawMiniGraphicExt(drawto, gc,
1472 DX + ED_WIN_MB_LEFT_XPOS,
1473 DY + ED_WIN_MB_LEFT_YPOS,
1474 el2gfx(new_element1));
1476 else if (button == 2)
1478 new_element2 = element;
1479 DrawMiniGraphicExt(drawto, gc,
1480 DX + ED_WIN_MB_MIDDLE_XPOS,
1481 DY + ED_WIN_MB_MIDDLE_YPOS,
1482 el2gfx(new_element2));
1486 new_element3 = element;
1487 DrawMiniGraphicExt(drawto, gc,
1488 DX + ED_WIN_MB_RIGHT_XPOS,
1489 DY + ED_WIN_MB_RIGHT_YPOS,
1490 el2gfx(new_element3));
1493 redraw_mask |= REDRAW_DOOR_1;
1496 void LevelEd(int mx, int my, int button)
1498 static int last_button = 0;
1499 static int in_field_pressed = FALSE;
1500 static boolean use_floodfill = FALSE;
1504 int x = (mx-SX)/MINI_TILEX;
1505 int y = (my-SY)/MINI_TILEY;
1509 HandlePressedControlButtons();
1510 HandleDrawingFunctions(mx, my, button);
1513 if (use_floodfill) /********** FLOOD FILL **********/
1521 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1526 if (x>lev_fieldx || y>lev_fieldy ||
1527 (x==0 && level_xpos<0) ||
1528 (x==ED_FIELDX-1 && level_xpos>lev_fieldx-ED_FIELDX) ||
1529 (y==0 && level_ypos<0) ||
1530 (y==ED_FIELDY-1 && level_ypos>lev_fieldy-ED_FIELDY))
1533 from_x = x+level_xpos;
1534 from_y = y+level_ypos;
1535 fill_element = (button==1 ? new_element1 :
1536 button==2 ? new_element2 :
1537 button==3 ? new_element3 : 0);
1539 FloodFill(from_x,from_y,fill_element);
1540 DrawMiniLevel(level_xpos,level_ypos);
1543 use_floodfill = FALSE;
1544 CloseDoor(DOOR_CLOSE_1);
1545 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1554 else /********** EDIT/CTRL-FENSTER **********/
1556 static unsigned long choice_delay = 0;
1557 int choice = CheckElemButtons(mx,my,button);
1558 int elem_pos = choice-ED_BUTTON_ELEM;
1560 if (((choice == ED_BUTTON_EUP && element_shift>0) ||
1561 (choice == ED_BUTTON_EDOWN &&
1562 element_shift<elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)) &&
1563 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1565 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
1569 step = (button==1 ? MAX_ELEM_X : button==2 ? 5*MAX_ELEM_X :
1571 element_shift += (choice==ED_BUTTON_EUP ? -step : step);
1573 step = step * MAX_ELEM_X * (choice == ED_BUTTON_EUP ? -1 : +1);
1574 element_shift += step;
1577 if (element_shift<0)
1579 if (element_shift>elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)
1580 element_shift = elements_in_list-MAX_ELEM_X*MAX_ELEM_Y;
1581 if (element_shift % MAX_ELEM_X)
1582 element_shift += MAX_ELEM_X-(element_shift % MAX_ELEM_X);
1584 for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
1585 DrawElemButton(i+2,ED_BUTTON_RELEASED);
1587 else if (elem_pos>=0 && elem_pos<MAX_ELEM_X*MAX_ELEM_Y)
1591 if (elem_pos+element_shift < elements_in_list)
1592 new_element = editor_element[elem_pos+element_shift];
1594 new_element = EL_LEERRAUM;
1596 PickDrawingElement(last_button, new_element);
1598 if (!HAS_CONTENT(properties_element))
1600 properties_element = new_element;
1601 if (edit_mode == ED_MODE_PROPERTIES)
1602 DrawPropertiesWindow();
1606 if (edit_mode == ED_MODE_DRAWING) /********** EDIT-FENSTER **********/
1613 switch(CheckEditButtons(mx,my,button))
1615 case ED_BUTTON_CTRL:
1616 CloseDoor(DOOR_CLOSE_2);
1617 DrawControlWindow();
1618 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1619 DOOR_GFX_PAGEX4,DOOR_GFX_PAGEY1+80,
1621 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1622 OpenDoor(DOOR_OPEN_2);
1623 edit_mode = ED_MODE_INFO;
1625 case ED_BUTTON_FILL:
1626 Request("Caution ! Flood fill mode ! Choose area !",REQ_OPEN);
1627 use_floodfill = TRUE;
1630 case ED_BUTTON_LEFT:
1633 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1635 if (lev_fieldx<ED_FIELDX-2)
1638 level_xpos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1642 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_RIGHT);
1644 DrawMiniLevel(level_xpos,level_ypos);
1647 case ED_BUTTON_RIGHT:
1648 if (level_xpos<=lev_fieldx-ED_FIELDX)
1650 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1652 if (lev_fieldx<ED_FIELDX-2)
1655 level_xpos += (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
1656 if (level_xpos>lev_fieldx-ED_FIELDX+1)
1657 level_xpos = lev_fieldx-ED_FIELDX+1;
1659 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_LEFT);
1661 DrawMiniLevel(level_xpos,level_ypos);
1667 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1669 if (lev_fieldy<ED_FIELDY-2)
1672 level_ypos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1676 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_DOWN);
1678 DrawMiniLevel(level_xpos,level_ypos);
1681 case ED_BUTTON_DOWN:
1682 if (level_ypos<=lev_fieldy-ED_FIELDY)
1684 if (!DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1686 if (lev_fieldy<ED_FIELDY-2)
1689 level_ypos += (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
1690 if (level_ypos>lev_fieldy-ED_FIELDY+1)
1691 level_ypos = lev_fieldy-ED_FIELDY+1;
1693 ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_UP);
1695 DrawMiniLevel(level_xpos,level_ypos);
1708 if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
1712 if (button && !motion_status)
1713 in_field_pressed = TRUE;
1715 if (!button || !in_field_pressed || button<1 || button>3 ||
1716 (y==0 && level_ypos<0) ||
1717 (y==ED_FIELDY-1 && level_ypos>lev_fieldy-ED_FIELDY) ||
1718 (x==0 && level_xpos<0) ||
1719 (x==ED_FIELDX-1 && level_xpos>lev_fieldx-ED_FIELDX) ||
1720 x>lev_fieldx || y>lev_fieldy)
1723 new_element = (button==1 ? new_element1 :
1724 button==2 ? new_element2 :
1725 button==3 ? new_element3 : 0);
1727 if (new_element != Feld[x+level_xpos][y+level_ypos])
1729 if (new_element==EL_SPIELFIGUR) /* Jeder nur EINE Figur bitte... */
1733 for(x=0;x<lev_fieldx;x++) for(y=0;y<lev_fieldy;y++)
1735 if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1)
1737 Feld[x][y] = EL_LEERRAUM;
1738 if (x-level_xpos>=0 && x-level_xpos<ED_FIELDX &&
1739 y-level_ypos>=0 && y-level_ypos<ED_FIELDY)
1740 DrawMiniElement(x-level_xpos,y-level_ypos,EL_LEERRAUM);
1745 Feld[x+level_xpos][y+level_ypos] = new_element;
1746 DrawMiniElement(x,y,new_element);
1749 else if (!motion_status) /* Mauszeiger nicht im Level-Feld */
1750 in_field_pressed = FALSE;
1757 else if (edit_mode == ED_MODE_INFO)/********** KONTROLL-FENSTER **********/
1759 int choice = CheckCountButtons(mx,my,button);
1760 int step = (button==1 ? 1 : button==2 ? 5 : button==3 ? 10 : 0);
1762 if (choice >= 0 && choice < 36 &&
1763 DelayReached(&choice_delay, GADGET_FRAME_DELAY))
1772 level.score[choice] += step;
1773 if (level.score[choice]<0)
1774 level.score[choice] = 0;
1775 else if (level.score[choice]>255)
1776 level.score[choice] = 255;
1778 else if (choice==11)
1780 level.tempo_amoebe += step;
1781 if (level.tempo_amoebe<0)
1782 level.tempo_amoebe = 0;
1783 else if (level.tempo_amoebe>255)
1784 level.tempo_amoebe = 255;
1786 else if (choice==12)
1788 level.dauer_sieb += step;
1789 if (level.dauer_sieb<0)
1790 level.dauer_sieb = 0;
1791 else if (level.dauer_sieb>255)
1792 level.dauer_sieb = 255;
1794 else if (choice==13)
1796 level.dauer_ablenk += step;
1797 if (level.dauer_ablenk<0)
1798 level.dauer_ablenk = 0;
1799 else if (level.dauer_ablenk>255)
1800 level.dauer_ablenk = 255;
1802 else if (choice==14)
1804 level.edelsteine += step;
1805 if (level.edelsteine<0)
1806 level.edelsteine = 0;
1807 else if (level.edelsteine>999)
1808 level.edelsteine = 999;
1810 else if (choice==15)
1815 else if (level.time>999)
1818 else if (choice==16)
1821 if (lev_fieldx<MIN_LEV_FIELDX)
1822 lev_fieldx = MIN_LEV_FIELDX;
1823 else if (lev_fieldx>MAX_LEV_FIELDX)
1824 lev_fieldx = MAX_LEV_FIELDX;
1825 level.fieldx = lev_fieldx;
1827 else if (choice==17)
1830 if (lev_fieldy<MIN_LEV_FIELDY)
1831 lev_fieldy = MIN_LEV_FIELDY;
1832 else if (lev_fieldy>MAX_LEV_FIELDY)
1833 lev_fieldy = MAX_LEV_FIELDY;
1834 level.fieldy = lev_fieldy;
1838 DrawText(ED_COUNT_VALUE_XPOS,
1839 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1840 int2str(level.score[choice],3),FS_SMALL,FC_YELLOW);
1841 else if (choice==11)
1842 DrawText(ED_COUNT_VALUE_XPOS,
1843 ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
1844 int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
1845 else if (choice==12)
1846 DrawText(ED_COUNT_VALUE_XPOS,
1847 ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
1848 int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
1849 else if (choice==13)
1850 DrawText(ED_COUNT_VALUE_XPOS,
1851 ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
1852 int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
1853 else if (choice==14)
1854 DrawText(ED_COUNT_VALUE_XPOS,
1855 ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
1856 int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
1857 else if (choice==15)
1858 DrawText(ED_COUNT_VALUE_XPOS,
1859 ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
1860 int2str(level.time,3),FS_SMALL,FC_YELLOW);
1861 else if (choice==16)
1862 DrawText(ED_SIZE_VALUE_XPOS,
1863 ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
1864 int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
1865 else if (choice==17)
1866 DrawText(ED_SIZE_VALUE_XPOS,
1867 ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
1868 int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
1870 redraw_mask &= ~REDRAW_FIELD;
1872 XCopyArea(display,drawto,window,gc,
1873 ED_COUNT_VALUE_XPOS,
1874 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
1875 3*FONT2_XSIZE,FONT2_YSIZE,
1876 ED_COUNT_VALUE_XPOS,
1877 ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE);
1879 XCopyArea(display,drawto,window,gc,
1881 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE,
1882 3*FONT2_XSIZE,FONT2_YSIZE,
1884 ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE);
1892 switch(CheckCtrlButtons(mx,my,button))
1894 case ED_BUTTON_EDIT:
1895 CloseDoor(DOOR_CLOSE_2);
1896 AdjustLevelScrollPosition();
1897 DrawMiniLevel(level_xpos,level_ypos);
1898 XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
1899 DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
1901 DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
1902 OpenDoor(DOOR_OPEN_2);
1903 edit_mode = ED_MODE_DRAWING;
1905 case ED_BUTTON_CLEAR:
1906 if (Request("Are you sure to clear this level ?",REQ_ASK))
1908 for(x=0;x<MAX_LEV_FIELDX;x++)
1909 for(y=0;y<MAX_LEV_FIELDY;y++)
1910 Feld[x][y] = EL_ERDREICH;
1911 DrawMiniLevel(level_xpos,level_ypos);
1914 case ED_BUTTON_UNDO:
1915 if (leveldir[leveldir_nr].readonly ||
1916 Request("Exit without saving ?",REQ_ASK | REQ_STAY_OPEN))
1918 CloseDoor(DOOR_CLOSE_ALL);
1919 game_status=MAINMENU;
1924 CloseDoor(DOOR_CLOSE_1);
1925 OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
1928 case ED_BUTTON_EXIT:
1930 int figur_vorhanden = FALSE;
1932 if (leveldir[leveldir_nr].readonly)
1934 Request("This level is read only !",REQ_CONFIRM);
1938 for(y=0;y<lev_fieldy;y++)
1939 for(x=0;x<lev_fieldx;x++)
1940 if (Feld[x][y] == EL_SPIELFIGUR ||
1941 Feld[x][y] == EL_SPIELER1 ||
1942 Feld[x][y] == EL_SP_MURPHY)
1943 figur_vorhanden = TRUE;
1945 if (!figur_vorhanden)
1946 Request("No Level without Gregor Mc Duffin please !",
1950 if (Request("Save this level and kill the old ?",
1951 REQ_ASK | REQ_STAY_OPEN))
1953 for(x=0;x<lev_fieldx;x++)
1954 for(y=0;y<lev_fieldy;y++)
1955 Ur[x][y]=Feld[x][y];
1956 SaveLevel(level_nr);
1958 CloseDoor(DOOR_CLOSE_ALL);
1959 game_status=MAINMENU;
1972 if (mx>=ED_COUNT_GADGET_XPOS &&
1973 mx<ED_COUNT_GADGET_XPOS+31*FONT2_XSIZE+10 &&
1974 my>=ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE &&
1975 my<ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE+ED_WIN_COUNT_YSIZE)
1980 DrawText(ED_COUNT_GADGET_XPOS+5,
1981 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1982 level.name,FS_SMALL,FC_GREEN);
1983 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1984 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1985 "<",FS_SMALL,FC_RED);
1992 name_typing = FALSE;
1993 DrawText(ED_COUNT_GADGET_XPOS+5,
1994 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1995 level.name,FS_SMALL,FC_YELLOW);
1996 DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
1997 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
1998 " ",FS_SMALL,FC_RED);
2002 if (mx>=SX+29*MINI_TILEX && mx<SX+30*MINI_TILEX &&
2003 my>=SY+26*MINI_TILEY && my<SY+27*MINI_TILEY)
2007 if (!button || button<1 || button>3)
2010 new_element = (button==1 ? new_element1 :
2011 button==2 ? new_element2 :
2012 button==3 ? new_element3 : 0);
2014 if (new_element != level.amoebe_inhalt)
2016 level.amoebe_inhalt = new_element;
2017 DrawMiniElement(29,26,new_element);
2021 if (mx>=SX+1*MINI_TILEX && mx<SX+(1+4*5)*MINI_TILEX &&
2022 my>=SY+2*MINI_TILEY && my<SY+(2+3)*MINI_TILEY)
2024 int x = (mx-SX-1*MINI_TILEX)/MINI_TILEX;
2025 int y = (my-SY-2*MINI_TILEY)/MINI_TILEY;
2030 if (i>=0 && i<43 && x>=0 && x<3 && y>=0 && y<3)
2032 if (button && !motion_status)
2033 in_field_pressed = TRUE;
2035 if (!button || !in_field_pressed || button<1 || button>3)
2038 new_element = (button==1 ? new_element1 :
2039 button==2 ? new_element2 :
2040 button==3 ? new_element3 : 0);
2042 if (new_element != level.mampfer_inhalt[i][x][y])
2044 level.mampfer_inhalt[i][x][y] = new_element;
2045 DrawMiniElement(1+5*i+x,2+y,new_element);
2048 else if (!motion_status)/* Mauszeiger nicht im Cruncher-Feld */
2049 in_field_pressed = FALSE;
2051 else if (!motion_status) /* Mauszeiger nicht im Cruncher-Feld */
2052 in_field_pressed = FALSE;
2056 last_button = button;
2061 void LevelNameTyping(KeySym key)
2063 unsigned char ascii = 0;
2064 int len = strlen(level.name);
2069 if (key>=XK_A && key<=XK_Z)
2070 ascii = 'A'+(char)(key-XK_A);
2071 else if (key>=XK_a && key<=XK_z)
2072 ascii = 'a'+(char)(key-XK_a);
2073 else if (key>=XK_0 && key<=XK_9)
2074 ascii = '0'+(char)(key-XK_0);
2076 else if (key>=XK_space && key<=XK_at)
2077 ascii = ' '+(char)(key-XK_space);
2078 else if (key==XK_Adiaeresis)
2080 else if (key==XK_Odiaeresis)
2082 else if (key==XK_Udiaeresis)
2084 else if (key==XK_adiaeresis)
2086 else if (key==XK_odiaeresis)
2088 else if (key==XK_udiaeresis)
2090 else if (key==XK_underscore)
2094 if (ascii && len<MAX_LEVNAMLEN-2)
2096 level.name[len] = ascii;
2097 level.name[len+1] = 0;
2100 DrawTextExt(drawto,gc,
2101 ED_COUNT_GADGET_XPOS+5,
2102 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2103 level.name,FS_SMALL,FC_GREEN);
2104 DrawTextExt(window,gc,
2105 ED_COUNT_GADGET_XPOS+5,
2106 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2107 level.name,FS_SMALL,FC_GREEN);
2108 DrawTextExt(drawto,gc,
2109 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2110 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2111 "<",FS_SMALL,FC_RED);
2112 DrawTextExt(window,gc,
2113 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2114 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2115 "<",FS_SMALL,FC_RED);
2117 else if ((key==XK_Delete || key==XK_BackSpace) && len>0)
2119 level.name[len-1] = 0;
2122 DrawTextExt(drawto,gc,
2123 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2124 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2125 "< ",FS_SMALL,FC_GREEN);
2126 DrawTextExt(window,gc,
2127 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2128 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2129 "< ",FS_SMALL,FC_GREEN);
2131 else if (key==XK_Return)
2133 DrawTextExt(drawto,gc,
2134 ED_COUNT_GADGET_XPOS+5,
2135 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2136 level.name,FS_SMALL,FC_YELLOW);
2137 DrawTextExt(window,gc,
2138 ED_COUNT_GADGET_XPOS+5,
2139 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2140 level.name,FS_SMALL,FC_YELLOW);
2141 DrawTextExt(drawto,gc,
2142 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2143 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2144 " ",FS_SMALL,FC_YELLOW);
2145 DrawTextExt(window,gc,
2146 ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
2147 ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
2148 " ",FS_SMALL,FC_YELLOW);
2150 name_typing = FALSE;
2154 static void DrawCounterValueField(int counter_id, int value)
2156 int x = SX + counterbutton_info[counter_id].x + ED_WIN_COUNT_XPOS;
2157 int y = SY + counterbutton_info[counter_id].y;
2159 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
2160 DOOR_GFX_PAGEX4 + ED_WIN_COUNT_XPOS,
2161 DOOR_GFX_PAGEY1 + ED_WIN_COUNT_YPOS,
2162 ED_WIN_COUNT_XSIZE, ED_WIN_COUNT_YSIZE,
2165 DrawText(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2166 int2str(value, 3), FS_SMALL, FC_YELLOW);
2169 static void DrawDrawingWindow()
2172 UnmapLevelEditorWindowGadgets();
2173 AdjustLevelScrollPosition();
2174 AdjustEditorScrollbar(ED_CTRL_ID_SCROLL_HORIZONTAL);
2175 AdjustEditorScrollbar(ED_CTRL_ID_SCROLL_VERTICAL);
2176 DrawMiniLevel(level_xpos, level_ypos);
2177 MapMainDrawingArea();
2180 static void DrawElementContentAreas()
2182 int *num_areas = &MampferMax;
2183 int area_x = ED_AREA_ELEMCONT_XPOS / MINI_TILEX;
2184 int area_y = ED_AREA_ELEMCONT_YPOS / MINI_TILEY;
2185 int area_sx = SX + ED_AREA_ELEMCONT_XPOS;
2186 int area_sy = SY + ED_AREA_ELEMCONT_YPOS;
2189 for (i=0; i<MAX_ELEMCONT; i++)
2192 ElementContent[i][x][y] = level.mampfer_inhalt[i][x][y];
2194 for (i=0; i<MAX_ELEMCONT; i++)
2195 UnmapDrawingArea(ED_CTRL_ID_ELEMCONT_0 + i);
2197 /* display counter to choose number of element content areas */
2198 gadget_areas_value = num_areas;
2199 DrawCounterValueField(ED_COUNTER_ELEMCONT, *gadget_areas_value);
2200 x = counterbutton_info[ED_COUNTER_ELEMCONT].x + DXSIZE;
2201 y = counterbutton_info[ED_COUNTER_ELEMCONT].y;
2202 DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2203 FC_YELLOW, "number of content areas");
2204 MapCounterButtons(ED_COUNTER_ELEMCONT);
2206 /* delete content areas in case of reducing number of them */
2207 XFillRectangle(display, backbuffer, gc,
2208 SX, area_sy - MINI_TILEX,
2209 SXSIZE, 12 * MINI_TILEY);
2211 /* draw some decorative border for the objects */
2212 for (i=0; i<*num_areas; i++)
2216 DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
2219 XFillRectangle(display, drawto, gc,
2220 area_sx + 5 * (i % 4) * MINI_TILEX + MINI_TILEX/2 - 1,
2221 area_sy + 6 * (i / 4) * MINI_TILEY + MINI_TILEY/2 - 1,
2222 3 * MINI_TILEX + 2, 3 * MINI_TILEY + 2);
2225 /* copy border to the right location */
2226 XCopyArea(display, drawto, drawto, gc,
2227 area_sx, area_sy, (5 * 4 + 1) * MINI_TILEX, 12 * MINI_TILEY,
2228 area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
2230 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 0 * MINI_TILEY + 1,
2231 "Content", FS_SMALL, FC_YELLOW);
2232 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 1 * MINI_TILEY + 1,
2233 "when", FS_SMALL, FC_YELLOW);
2234 DrawText(area_sx + (5 * 4 - 1) * MINI_TILEX, area_sy + 2 * MINI_TILEY + 1,
2235 "smashed", FS_SMALL, FC_YELLOW);
2237 for (i=0; i<*num_areas; i++)
2241 DrawMiniElement(area_x + 5 * (i % 4) + x, area_y + 6 * (i / 4) + y,
2242 ElementContent[i][x][y]);
2244 DrawTextF(area_sx - SX + 5 * (i % 4) * MINI_TILEX + MINI_TILEX + 1,
2245 area_sy - SY + 6 * (i / 4) * MINI_TILEY + 4 * MINI_TILEY - 4,
2246 FC_YELLOW, "%d", i + 1);
2249 for (i=0; i<*num_areas; i++)
2250 MapDrawingArea(ED_CTRL_ID_ELEMCONT_0 + i);
2253 static void DrawAmoebaContentArea()
2255 int area_x = ED_AREA_ELEMCONT_XPOS / MINI_TILEX;
2256 int area_y = ED_AREA_ELEMCONT_YPOS / MINI_TILEY;
2257 int area_sx = SX + ED_AREA_ELEMCONT_XPOS;
2258 int area_sy = SY + ED_AREA_ELEMCONT_YPOS;
2261 ElementContent[0][0][0] = level.amoebe_inhalt;
2263 /* draw decorative border for the object */
2266 DrawMiniElement(area_x + x, area_y + y, EL_ERDREICH);
2268 XFillRectangle(display, drawto, gc,
2269 area_sx + MINI_TILEX/2 - 1, area_sy + MINI_TILEY/2 - 1,
2270 MINI_TILEX + 2, MINI_TILEY + 2);
2272 /* copy border to the right location */
2273 XCopyArea(display, drawto, drawto, gc,
2274 area_sx, area_sy, 3 * MINI_TILEX, 3 * MINI_TILEY,
2275 area_sx - MINI_TILEX/2, area_sy - MINI_TILEY/2);
2277 DrawText(area_sx + TILEX, area_sy + 1, "Content of amoeba",
2278 FS_SMALL, FC_YELLOW);
2280 DrawMiniElement(area_x, area_y, ElementContent[0][0][0]);
2282 MapDrawingArea(ED_CTRL_ID_AMOEBA_CONTENT);
2285 #define TEXT_COLLECTING "Score for collecting"
2286 #define TEXT_SMASHING "Score for smashing"
2287 #define TEXT_CRACKING "Score for cracking"
2288 #define TEXT_SPEED "Speed of amoeba growth"
2289 #define TEXT_DURATION "Duration when activated"
2291 static void DrawPropertiesWindow()
2294 int num_elements_in_level;
2300 } elements_with_counter[] =
2302 { EL_EDELSTEIN, &level.score[0], TEXT_COLLECTING },
2303 { EL_EDELSTEIN_BD, &level.score[0], TEXT_COLLECTING },
2304 { EL_EDELSTEIN_GELB,&level.score[0], TEXT_COLLECTING },
2305 { EL_EDELSTEIN_ROT, &level.score[0], TEXT_COLLECTING },
2306 { EL_EDELSTEIN_LILA,&level.score[0], TEXT_COLLECTING },
2307 { EL_DIAMANT, &level.score[1], TEXT_COLLECTING },
2308 { EL_KAEFER_R, &level.score[2], TEXT_SMASHING },
2309 { EL_KAEFER_O, &level.score[2], TEXT_SMASHING },
2310 { EL_KAEFER_L, &level.score[2], TEXT_SMASHING },
2311 { EL_KAEFER_U, &level.score[2], TEXT_SMASHING },
2312 { EL_BUTTERFLY_R, &level.score[2], TEXT_SMASHING },
2313 { EL_BUTTERFLY_O, &level.score[2], TEXT_SMASHING },
2314 { EL_BUTTERFLY_L, &level.score[2], TEXT_SMASHING },
2315 { EL_BUTTERFLY_U, &level.score[2], TEXT_SMASHING },
2316 { EL_FLIEGER_R, &level.score[3], TEXT_SMASHING },
2317 { EL_FLIEGER_O, &level.score[3], TEXT_SMASHING },
2318 { EL_FLIEGER_L, &level.score[3], TEXT_SMASHING },
2319 { EL_FLIEGER_U, &level.score[3], TEXT_SMASHING },
2320 { EL_FIREFLY_R, &level.score[3], TEXT_SMASHING },
2321 { EL_FIREFLY_O, &level.score[3], TEXT_SMASHING },
2322 { EL_FIREFLY_L, &level.score[3], TEXT_SMASHING },
2323 { EL_FIREFLY_U, &level.score[3], TEXT_SMASHING },
2324 { EL_MAMPFER, &level.score[4], TEXT_SMASHING },
2325 { EL_MAMPFER2, &level.score[4], TEXT_SMASHING },
2326 { EL_ROBOT, &level.score[5], TEXT_SMASHING },
2327 { EL_PACMAN_R, &level.score[6], TEXT_SMASHING },
2328 { EL_PACMAN_O, &level.score[6], TEXT_SMASHING },
2329 { EL_PACMAN_L, &level.score[6], TEXT_SMASHING },
2330 { EL_PACMAN_U, &level.score[6], TEXT_SMASHING },
2331 { EL_KOKOSNUSS, &level.score[7], TEXT_CRACKING },
2332 { EL_DYNAMIT_AUS, &level.score[8], TEXT_COLLECTING },
2333 { EL_SCHLUESSEL1, &level.score[9], TEXT_COLLECTING },
2334 { EL_SCHLUESSEL2, &level.score[9], TEXT_COLLECTING },
2335 { EL_SCHLUESSEL3, &level.score[9], TEXT_COLLECTING },
2336 { EL_SCHLUESSEL4, &level.score[9], TEXT_COLLECTING },
2337 { EL_AMOEBE_NASS, &level.tempo_amoebe, TEXT_SPEED },
2338 { EL_AMOEBE_NORM, &level.tempo_amoebe, TEXT_SPEED },
2339 { EL_AMOEBE_VOLL, &level.tempo_amoebe, TEXT_SPEED },
2340 { EL_AMOEBE_BD, &level.tempo_amoebe, TEXT_SPEED },
2341 { EL_SIEB_INAKTIV, &level.dauer_sieb, TEXT_DURATION },
2342 { EL_ABLENK_AUS, &level.dauer_ablenk, TEXT_DURATION },
2347 UnmapLevelEditorWindowGadgets();
2349 /* draw some decorative border for the object */
2352 DrawMiniElement(2 + x , 2 + y, EL_ERDREICH);
2354 XFillRectangle(display, drawto, gc,
2355 SX + TILEX + MINI_TILEX/2 - 1,
2356 SY + TILEY + MINI_TILEY/2 - 1,
2357 TILEX + 2, TILEY + 2);
2359 /* copy border to the right location */
2360 XCopyArea(display, drawto, drawto, gc,
2361 SX + TILEX, SY + TILEY,
2362 2 * TILEX, 2 * TILEY,
2363 SX + TILEX - MINI_TILEX/2, SY + TILEY - MINI_TILEY/2);
2365 DrawGraphic(1, 1, el2gfx(properties_element));
2366 DrawText(SX + 3*TILEX, SY + 5*TILEY/4, "Element Properties",
2367 FS_SMALL, FC_YELLOW);
2369 num_elements_in_level = 0;
2370 for (y=0; y<lev_fieldy; y++)
2371 for (x=0; x<lev_fieldx; x++)
2372 if (Feld[x][y] == properties_element)
2373 num_elements_in_level++;
2375 DrawTextF(ED_PROPERTIES_XPOS, 5*TILEY, FC_YELLOW, "%d x contained in level",
2376 num_elements_in_level);
2378 /* check if there are elements where a score can be chosen for */
2379 for (i=0; elements_with_counter[i].element != -1; i++)
2381 if (elements_with_counter[i].element == properties_element)
2383 int x = counterbutton_info[ED_COUNTER_SCORE].x + DXSIZE;
2384 int y = counterbutton_info[ED_COUNTER_SCORE].y;
2386 gadget_score_value = elements_with_counter[i].counter_value;
2387 DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value);
2388 DrawTextF(x + ED_COUNT_VALUE_XOFFSET, y + ED_COUNT_VALUE_YOFFSET,
2389 FC_YELLOW, elements_with_counter[i].text);
2390 MapCounterButtons(ED_COUNTER_SCORE);
2395 if (HAS_CONTENT(properties_element))
2397 if (IS_AMOEBOID(properties_element))
2398 DrawAmoebaContentArea();
2400 DrawElementContentAreas();
2403 /* TEST ONLY: level name text input gadget */
2404 MapTextInputGadget(ED_CTRL_ID_LEVEL_NAME);
2407 static void swap_numbers(int *i1, int *i2)
2415 static void swap_number_pairs(int *x1, int *y1, int *x2, int *y2)
2427 static void DrawLineElement(int sx, int sy, int element, boolean change_level)
2429 int lx = sx + level_xpos;
2430 int ly = sy + level_ypos;
2432 DrawMiniElement(sx, sy, (element < 0 ? Feld[lx][ly] : element));
2435 Feld[lx][ly] = element;
2438 static void DrawLine(int from_x, int from_y, int to_x, int to_y,
2439 int element, boolean change_level)
2441 if (from_y == to_y) /* horizontal line */
2447 swap_numbers(&from_x, &to_x);
2449 for (x=from_x; x<=to_x; x++)
2450 DrawLineElement(x, y, element, change_level);
2452 else if (from_x == to_x) /* vertical line */
2458 swap_numbers(&from_y, &to_y);
2460 for (y=from_y; y<=to_y; y++)
2461 DrawLineElement(x, y, element, change_level);
2463 else /* diagonal line */
2465 int len_x = ABS(to_x - from_x);
2466 int len_y = ABS(to_y - from_y);
2469 if (len_y < len_x) /* a < 1 */
2471 float a = (float)len_y / (float)len_x;
2474 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2476 for (x=0; x<=len_x; x++)
2478 int y = (int)(a * x + 0.5) * (to_y < from_y ? -1 : +1);
2480 DrawLineElement(from_x + x, from_y + y, element, change_level);
2485 float a = (float)len_x / (float)len_y;
2488 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2490 for (y=0; y<=len_y; y++)
2492 int x = (int)(a * y + 0.5) * (to_x < from_x ? -1 : +1);
2494 DrawLineElement(from_x + x, from_y + y, element, change_level);
2500 static void DrawRectangle(int from_x, int from_y, int to_x, int to_y,
2501 int element, boolean change_level)
2503 DrawLine(from_x, from_y, from_x, to_y, element, change_level);
2504 DrawLine(from_x, to_y, to_x, to_y, element, change_level);
2505 DrawLine(to_x, to_y, to_x, from_y, element, change_level);
2506 DrawLine(to_x, from_y, from_x, from_y, element, change_level);
2509 static void DrawFilledBox(int from_x, int from_y, int to_x, int to_y,
2510 int element, boolean change_level)
2515 swap_number_pairs(&from_x, &from_y, &to_x, &to_y);
2517 for (y=from_y; y<=to_y; y++)
2518 DrawLine(from_x, y, to_x, y, element, change_level);
2521 static void DrawAreaBorder(int from_x, int from_y, int to_x, int to_y)
2523 int from_sx, from_sy;
2527 swap_numbers(&from_x, &to_x);
2530 swap_numbers(&from_y, &to_y);
2532 from_sx = SX + from_x * MINI_TILEX;
2533 from_sy = SY + from_y * MINI_TILEY;
2534 to_sx = SX + to_x * MINI_TILEX + MINI_TILEX - 1;
2535 to_sy = SY + to_y * MINI_TILEY + MINI_TILEY - 1;
2537 XSetForeground(display, gc, WhitePixel(display, screen));
2539 XDrawLine(display, drawto, gc, from_sx, from_sy, to_sx, from_sy);
2540 XDrawLine(display, drawto, gc, to_sx, from_sy, to_sx, to_sy);
2541 XDrawLine(display, drawto, gc, to_sx, to_sy, from_sx, to_sy);
2542 XDrawLine(display, drawto, gc, from_sx, to_sy, from_sx, from_sy);
2544 XSetForeground(display, gc, BlackPixel(display, screen));
2546 if (from_x == to_x && from_y == to_y)
2547 MarkTileDirty(from_x/2, from_y/2);
2549 redraw_mask |= REDRAW_FIELD;
2552 static void SelectArea(int from_x, int from_y, int to_x, int to_y,
2553 int element, boolean change_level)
2555 if (element == -1 || change_level)
2556 DrawRectangle(from_x, from_y, to_x, to_y, -1, FALSE);
2558 DrawAreaBorder(from_x, from_y, to_x, to_y);
2561 /* values for CopyBrushExt() */
2562 #define CB_AREA_TO_BRUSH 0
2563 #define CB_BRUSH_TO_CURSOR 1
2564 #define CB_BRUSH_TO_LEVEL 2
2565 #define CB_DELETE_OLD_CURSOR 3
2567 static void CopyBrushExt(int from_x, int from_y, int to_x, int to_y, int mode)
2569 static short brush_buffer[ED_FIELDX][ED_FIELDY];
2570 static int brush_width, brush_height;
2571 static int last_cursor_x = -1, last_cursor_y = -1;
2572 static boolean delete_old_brush;
2575 if (mode == CB_DELETE_OLD_CURSOR && !delete_old_brush)
2578 if (mode == CB_AREA_TO_BRUSH)
2580 int from_lx, from_ly;
2583 swap_numbers(&from_x, &to_x);
2586 swap_numbers(&from_y, &to_y);
2588 brush_width = to_x - from_x + 1;
2589 brush_height = to_y - from_y + 1;
2591 from_lx = from_x + level_xpos;
2592 from_ly = from_y + level_ypos;
2594 for (y=0; y<brush_height; y++)
2595 for (x=0; x<brush_width; x++)
2596 brush_buffer[x][y] = Feld[from_lx + x][from_ly + y];
2598 delete_old_brush = FALSE;
2600 else if (mode == CB_BRUSH_TO_CURSOR || mode == CB_DELETE_OLD_CURSOR ||
2601 mode == CB_BRUSH_TO_LEVEL)
2603 int cursor_x = (mode == CB_DELETE_OLD_CURSOR ? last_cursor_x : from_x);
2604 int cursor_y = (mode == CB_DELETE_OLD_CURSOR ? last_cursor_y : from_y);
2605 int cursor_from_x = cursor_x - brush_width / 2;
2606 int cursor_from_y = cursor_y - brush_height / 2;
2607 int border_from_x = cursor_x, border_from_y = cursor_y;
2608 int border_to_x = cursor_x, border_to_y = cursor_y;
2610 if (mode != CB_DELETE_OLD_CURSOR && delete_old_brush)
2611 CopyBrushExt(0, 0, 0, 0, CB_DELETE_OLD_CURSOR);
2613 if (!IN_LEV_FIELD(cursor_x + level_xpos, cursor_y + level_ypos))
2615 delete_old_brush = FALSE;
2619 for (y=0; y<brush_height; y++)
2621 for (x=0; x<brush_width; x++)
2623 int sx = cursor_from_x + x;
2624 int sy = cursor_from_y + y;
2625 int lx = sx + level_xpos;
2626 int ly = sy + level_ypos;
2627 int element = (mode == CB_DELETE_OLD_CURSOR ? -1 : brush_buffer[x][y]);
2628 boolean change_level = (mode == CB_BRUSH_TO_LEVEL);
2630 if (IN_LEV_FIELD(lx, ly) &&
2631 sx >=0 && sx < ED_FIELDX && sy >=0 && sy < ED_FIELDY)
2633 if (sx < border_from_x)
2635 else if (sx > border_to_x)
2637 if (sy < border_from_y)
2639 else if (sy > border_to_y)
2642 DrawLineElement(sx, sy, element, change_level);
2648 printf("%d, %d - %d, %d in level and screen\n",
2649 border_from_x, border_from_y, border_to_x, border_to_y);
2652 if (mode != CB_DELETE_OLD_CURSOR)
2653 DrawAreaBorder(border_from_x, border_from_y, border_to_x, border_to_y);
2655 if (mode == CB_BRUSH_TO_LEVEL)
2656 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2658 last_cursor_x = cursor_x;
2659 last_cursor_y = cursor_y;
2660 delete_old_brush = TRUE;
2664 static void CopyAreaToBrush(int from_x, int from_y, int to_x, int to_y)
2666 CopyBrushExt(from_x, from_y, to_x, to_y, CB_AREA_TO_BRUSH);
2669 static void CopyBrushToLevel(int x, int y)
2671 CopyBrushExt(x, y, 0, 0, CB_BRUSH_TO_LEVEL);
2674 static void CopyBrushToCursor(int x, int y)
2676 CopyBrushExt(x, y, 0, 0, CB_BRUSH_TO_CURSOR);
2679 static void DeleteBrushFromCursor()
2681 CopyBrushExt(0, 0, 0, 0, CB_DELETE_OLD_CURSOR);
2684 static void FloodFill(int from_x, int from_y, int fill_element)
2688 static int check[4][2] = { {-1,0}, {0,-1}, {1,0}, {0,1} };
2689 static int safety = 0;
2691 /* check if starting field still has the desired content */
2692 if (Feld[from_x][from_y] == fill_element)
2697 if (safety > lev_fieldx*lev_fieldy)
2698 Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
2700 old_element = Feld[from_x][from_y];
2701 Feld[from_x][from_y] = fill_element;
2705 x = from_x + check[i][0];
2706 y = from_y + check[i][1];
2708 if (IN_LEV_FIELD(x,y) && Feld[x][y] == old_element)
2709 FloodFill(x, y, fill_element);
2715 /* values for DrawLevelText() modes */
2717 #define TEXT_SETCURSOR 1
2718 #define TEXT_WRITECHAR 2
2719 #define TEXT_BACKSPACE 3
2720 #define TEXT_NEWLINE 4
2723 static void DrawLevelText(int sx, int sy, char letter, int mode)
2725 static short delete_buffer[MAX_LEV_FIELDX];
2726 static int start_sx, start_sy;
2727 static int last_sx, last_sy;
2728 static boolean typing = FALSE;
2729 int letter_element = EL_CHAR_ASCII0 + letter;
2732 /* map lower case letters to upper case and convert special characters */
2733 if (letter >= 'a' && letter <= 'z')
2734 letter_element = EL_CHAR_ASCII0 + letter + (int)('A' - 'a');
2735 else if (letter == 'ä' || letter == 'Ä')
2736 letter_element = EL_CHAR_AE;
2737 else if (letter == 'ö' || letter == 'Ö')
2738 letter_element = EL_CHAR_OE;
2739 else if (letter == 'ü' || letter == 'Ü')
2740 letter_element = EL_CHAR_UE;
2741 else if (letter == '^')
2742 letter_element = EL_CHAR_COPY;
2744 letter_element = EL_CHAR_ASCII0 + letter;
2746 if (mode != TEXT_INIT)
2751 if (mode != TEXT_SETCURSOR)
2757 lx = last_sx + level_xpos;
2758 ly = last_sy + level_ypos;
2765 DrawLevelText(0, 0, 0, TEXT_END);
2768 start_sx = last_sx = sx;
2769 start_sy = last_sy = sy;
2770 DrawLevelText(sx, sy, 0, TEXT_SETCURSOR);
2773 case TEXT_SETCURSOR:
2774 DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
2775 DrawAreaBorder(sx, sy, sx, sy);
2780 case TEXT_WRITECHAR:
2781 if (letter_element >= EL_CHAR_START && letter_element <= EL_CHAR_END)
2783 delete_buffer[sx - start_sx] = Feld[lx][ly];
2784 Feld[lx][ly] = letter_element;
2786 if (sx + 1 < ED_FIELDX && lx + 1 < lev_fieldx)
2787 DrawLevelText(sx + 1, sy, 0, TEXT_SETCURSOR);
2788 else if (sy + 1 < ED_FIELDY && ly + 1 < lev_fieldy)
2789 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
2791 DrawLevelText(0, 0, 0, TEXT_END);
2795 case TEXT_BACKSPACE:
2798 Feld[lx - 1][ly] = delete_buffer[sx - start_sx - 1];
2799 DrawMiniElement(sx - 1, sy, new_element3);
2800 DrawLevelText(sx - 1, sy, 0, TEXT_SETCURSOR);
2805 if (sy + 1 < ED_FIELDY - 1 && ly + 1 < lev_fieldy - 1)
2806 DrawLevelText(start_sx, sy + 1, 0, TEXT_SETCURSOR);
2808 DrawLevelText(0, 0, 0, TEXT_END);
2812 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2813 DrawMiniElement(sx, sy, Feld[lx][ly]);
2822 static void SetTextCursor(int unused_sx, int unused_sy, int sx, int sy,
2823 int element, boolean change_level)
2825 int lx = sx + level_xpos;
2826 int ly = sy + level_ypos;
2829 DrawMiniElement(sx, sy, Feld[lx][ly]);
2831 DrawAreaBorder(sx, sy, sx, sy);
2834 static void CopyLevelToUndoBuffer(int mode)
2836 static boolean accumulated_undo = FALSE;
2837 boolean new_undo_buffer_position = TRUE;
2842 case UNDO_IMMEDIATE:
2843 accumulated_undo = FALSE;
2846 case UNDO_ACCUMULATE:
2847 if (accumulated_undo)
2848 new_undo_buffer_position = FALSE;
2849 accumulated_undo = TRUE;
2856 if (new_undo_buffer_position)
2858 /* new position in undo buffer ring */
2859 undo_buffer_position = (undo_buffer_position + 1) % NUM_UNDO_STEPS;
2861 if (undo_buffer_steps < NUM_UNDO_STEPS - 1)
2862 undo_buffer_steps++;
2865 for(x=0; x<lev_fieldx; x++)
2866 for(y=0; y<lev_fieldy; y++)
2867 UndoBuffer[undo_buffer_position][x][y] = Feld[x][y];
2870 printf("level saved to undo buffer\n");
2875 static void RandomPlacement(int button)
2880 new_element = (button == 1 ? new_element1 :
2881 button == 2 ? new_element2 :
2882 button == 3 ? new_element3 : 0);
2884 if (random_placement_method == RANDOM_USE_PERCENTAGE)
2886 for(x=0; x<lev_fieldx; x++)
2887 for(y=0; y<lev_fieldy; y++)
2888 if (RND(100) < random_placement_percentage)
2889 Feld[x][y] = new_element;
2893 int elements_left = random_placement_num_objects;
2895 while (elements_left > 0)
2897 x = RND(lev_fieldx);
2898 y = RND(lev_fieldy);
2900 if (Feld[x][y] != new_element)
2902 Feld[x][y] = new_element;
2908 DrawMiniLevel(level_xpos, level_ypos);
2909 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
2912 void WrapLevel(int dx, int dy)
2914 int wrap_dx = lev_fieldx - dx;
2915 int wrap_dy = lev_fieldy - dy;
2918 for(x=0; x<lev_fieldx; x++)
2919 for(y=0; y<lev_fieldy; y++)
2920 FieldBackup[x][y] = Feld[x][y];
2922 for(x=0; x<lev_fieldx; x++)
2923 for(y=0; y<lev_fieldy; y++)
2925 FieldBackup[(x + wrap_dx) % lev_fieldx][(y + wrap_dy) % lev_fieldy];
2927 DrawMiniLevel(level_xpos, level_ypos);
2928 CopyLevelToUndoBuffer(UNDO_ACCUMULATE);
2931 static void HandleDrawingAreas(struct GadgetInfo *gi)
2933 static boolean started_inside_drawing_area = FALSE;
2934 int id = gi->custom_id;
2935 boolean inside_drawing_area = !gi->event.off_borders;
2936 boolean button_press_event;
2937 boolean button_release_event;
2938 boolean draw_level = (id == ED_CTRL_ID_DRAWING_LEVEL);
2940 int button = gi->event.button;
2941 int sx = gi->event.x, sy = gi->event.y;
2942 int min_sx = 0, min_sy = 0;
2943 int max_sx = gi->drawing.area_xsize - 1, max_sy = gi->drawing.area_ysize - 1;
2945 int min_lx = 0, min_ly = 0;
2946 int max_lx = lev_fieldx - 1, max_ly = lev_fieldy - 1;
2950 if (edit_mode != ED_MODE_DRAWING)
2954 button_press_event = (gi->event.type == GD_EVENT_PRESSED);
2955 button_release_event = (gi->event.type == GD_EVENT_RELEASED);
2957 /* make sure to stay inside drawing area boundaries */
2958 sx = (sx < min_sx ? min_sx : sx > max_sx ? max_sx : sx);
2959 sy = (sy < min_sy ? min_sy : sy > max_sy ? max_sy : sy);
2963 /* get positions inside level field */
2964 lx = sx + level_xpos;
2965 ly = sy + level_ypos;
2967 /* make sure to stay inside level field boundaries */
2968 lx = (lx < min_lx ? min_lx : lx > max_lx ? max_lx : lx);
2969 ly = (ly < min_ly ? min_ly : ly > max_ly ? max_ly : ly);
2971 /* correct drawing area positions accordingly */
2972 sx = lx - level_xpos;
2973 sy = ly - level_ypos;
2976 if (button_press_event)
2977 started_inside_drawing_area = inside_drawing_area;
2979 if (!started_inside_drawing_area)
2982 if (!button && !button_release_event)
2985 new_element = (button == 1 ? new_element1 :
2986 button == 2 ? new_element2 :
2987 button == 3 ? new_element3 : 0);
2989 if (!draw_level && drawing_function != ED_CTRL_ID_SINGLE_ITEMS)
2992 switch (drawing_function)
2994 case ED_CTRL_ID_SINGLE_ITEMS:
2997 if (button_release_event)
2998 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3003 if (new_element != Feld[lx][ly])
3005 if (new_element == EL_SPIELFIGUR)
3007 /* remove player at old position */
3008 for(y=0; y<lev_fieldy; y++)
3010 for(x=0; x<lev_fieldx; x++)
3012 if (Feld[x][y] == EL_SPIELFIGUR || Feld[x][y] == EL_SPIELER1)
3014 Feld[x][y] = EL_LEERRAUM;
3015 if (x - level_xpos >= 0 && x - level_xpos < ED_FIELDX &&
3016 y - level_ypos >= 0 && y - level_ypos < ED_FIELDY)
3017 DrawMiniElement(x - level_xpos, y - level_ypos,
3024 Feld[lx][ly] = new_element;
3025 DrawMiniElement(sx, sy, new_element);
3030 DrawMiniGraphicExt(drawto, gc,
3031 gi->x + sx * MINI_TILEX,
3032 gi->y + sy * MINI_TILEY,
3033 el2gfx(new_element));
3034 DrawMiniGraphicExt(window, gc,
3035 gi->x + sx * MINI_TILEX,
3036 gi->y + sy * MINI_TILEY,
3037 el2gfx(new_element));
3039 if (id == ED_CTRL_ID_AMOEBA_CONTENT)
3040 level.amoebe_inhalt = new_element;
3041 else if (id >= ED_CTRL_ID_ELEMCONT_0 && id <= ED_CTRL_ID_ELEMCONT_7)
3042 level.mampfer_inhalt[id - ED_CTRL_ID_ELEMCONT_0][sx][sy] =
3047 case ED_CTRL_ID_CONNECTED_ITEMS:
3049 static int last_sx = -1;
3050 static int last_sy = -1;
3052 if (button_release_event)
3053 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3057 if (!button_press_event)
3058 DrawLine(last_sx, last_sy, sx, sy, new_element, TRUE);
3066 case ED_CTRL_ID_LINE:
3067 case ED_CTRL_ID_RECTANGLE:
3068 case ED_CTRL_ID_FILLED_BOX:
3069 case ED_CTRL_ID_BRUSH:
3070 case ED_CTRL_ID_TEXT:
3072 static int last_sx = -1;
3073 static int last_sy = -1;
3074 static int start_sx = -1;
3075 static int start_sy = -1;
3076 void (*draw_func)(int, int, int, int, int, boolean);
3078 if (drawing_function == ED_CTRL_ID_LINE)
3079 draw_func = DrawLine;
3080 else if (drawing_function == ED_CTRL_ID_RECTANGLE)
3081 draw_func = DrawRectangle;
3082 else if (drawing_function == ED_CTRL_ID_FILLED_BOX)
3083 draw_func = DrawFilledBox;
3084 else if (drawing_function == ED_CTRL_ID_BRUSH)
3085 draw_func = SelectArea;
3086 else /* (drawing_function == ED_CTRL_ID_TEXT) */
3087 draw_func = SetTextCursor;
3089 if (button_press_event)
3091 draw_func(sx, sy, sx, sy, new_element, FALSE);
3092 start_sx = last_sx = sx;
3093 start_sy = last_sy = sy;
3095 if (drawing_function == ED_CTRL_ID_TEXT)
3096 DrawLevelText(0, 0, 0, TEXT_END);
3098 else if (button_release_event)
3100 draw_func(start_sx, start_sy, sx, sy, new_element, TRUE);
3101 if (drawing_function == ED_CTRL_ID_BRUSH)
3103 CopyAreaToBrush(start_sx, start_sy, sx, sy);
3104 draw_with_brush = TRUE;
3106 else if (drawing_function == ED_CTRL_ID_TEXT)
3107 DrawLevelText(sx, sy, 0, TEXT_INIT);
3109 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3111 else if (last_sx != sx || last_sy != sy)
3113 draw_func(start_sx, start_sy, last_sx, last_sy, -1, FALSE);
3114 draw_func(start_sx, start_sy, sx, sy, new_element, FALSE);
3124 case ED_CTRL_ID_TEXT:
3126 DrawMiniElement(last_sx, last_sy, Feld[lx][ly]);
3127 DrawAreaBorder(sx, sy, sx, sy);
3132 if (button_press_event)
3133 DrawLevelText(sx, sy, 0, TEXT_INIT);
3139 case ED_CTRL_ID_FLOOD_FILL:
3140 if (button_press_event && Feld[lx][ly] != new_element)
3142 FloodFill(lx, ly, new_element);
3143 DrawMiniLevel(level_xpos, level_ypos);
3144 CopyLevelToUndoBuffer(UNDO_IMMEDIATE);
3148 case ED_CTRL_ID_PICK_ELEMENT:
3149 if (button_press_event)
3150 PickDrawingElement(button, Feld[lx][ly]);
3151 if (button_release_event)
3152 ClickOnGadget(level_editor_gadget[last_drawing_function]);
3160 static void HandleCounterButtons(struct GadgetInfo *gi)
3162 int id = gi->custom_id;
3163 int button = gi->event.button;
3164 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
3168 case ED_CTRL_ID_SCORE_DOWN:
3169 case ED_CTRL_ID_SCORE_UP:
3170 *gadget_score_value += (id == ED_CTRL_ID_SCORE_DOWN ? -step : step);
3171 if (*gadget_score_value < 0)
3172 *gadget_score_value = 0;
3173 else if (*gadget_score_value > 255)
3174 *gadget_score_value = 255;
3176 DrawCounterValueField(ED_COUNTER_SCORE, *gadget_score_value);
3179 case ED_CTRL_ID_ELEMCONT_DOWN:
3180 case ED_CTRL_ID_ELEMCONT_UP:
3181 *gadget_areas_value += (id == ED_CTRL_ID_ELEMCONT_DOWN ? -step : step);
3182 if (*gadget_areas_value < 1)
3183 *gadget_areas_value = 1;
3184 else if (*gadget_areas_value > MAX_ELEMCONT)
3185 *gadget_areas_value = MAX_ELEMCONT;
3187 DrawCounterValueField(ED_COUNTER_ELEMCONT, *gadget_areas_value);
3188 DrawElementContentAreas();
3196 static void HandleControlButtons(struct GadgetInfo *gi)
3198 int id = gi->custom_id;
3199 int button = gi->event.button;
3200 int step = (button == 1 ? 1 : button == 2 ? 5 : 10);
3202 int player_present = FALSE;
3203 int level_changed = FALSE;
3206 new_element = (button == 1 ? new_element1 :
3207 button == 2 ? new_element2 :
3208 button == 3 ? new_element3 : 0);
3210 if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT)
3211 DrawLevelText(0, 0, 0, TEXT_END);
3213 if (id < ED_NUM_CTRL1_BUTTONS && id != ED_CTRL_ID_PROPERTIES &&
3214 edit_mode != ED_MODE_DRAWING)
3216 DrawDrawingWindow();
3217 edit_mode = ED_MODE_DRAWING;
3222 case ED_CTRL_ID_SCROLL_LEFT:
3223 if (level_xpos >= 0)
3225 int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL;
3226 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3227 struct GadgetScrollbar *gs = &gi->scrollbar;
3229 if (lev_fieldx < ED_FIELDX - 2)
3233 if (level_xpos < -1)
3236 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_RIGHT);
3238 DrawMiniLevel(level_xpos, level_ypos);
3240 AdjustScrollbar(gi, gs->items_max, level_xpos + 1);
3244 case ED_CTRL_ID_SCROLL_RIGHT:
3245 if (level_xpos <= lev_fieldx - ED_FIELDX)
3247 int gadget_id = ED_CTRL_ID_SCROLL_HORIZONTAL;
3248 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3249 struct GadgetScrollbar *gs = &gi->scrollbar;
3251 if (lev_fieldx < ED_FIELDX - 2)
3255 if (level_xpos > lev_fieldx - ED_FIELDX + 1)
3256 level_xpos = lev_fieldx - ED_FIELDX + 1;
3258 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_LEFT);
3260 DrawMiniLevel(level_xpos, level_ypos);
3262 AdjustScrollbar(gi, gs->items_max, level_xpos + 1);
3266 case ED_CTRL_ID_SCROLL_UP:
3267 if (level_ypos >= 0)
3269 int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL;
3270 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3271 struct GadgetScrollbar *gs = &gi->scrollbar;
3273 if (lev_fieldy < ED_FIELDY - 2)
3277 if (level_ypos < -1)
3280 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_DOWN);
3282 DrawMiniLevel(level_xpos, level_ypos);
3284 AdjustScrollbar(gi, gs->items_max, level_ypos + 1);
3288 case ED_CTRL_ID_SCROLL_DOWN:
3289 if (level_ypos <= lev_fieldy - ED_FIELDY)
3291 int gadget_id = ED_CTRL_ID_SCROLL_VERTICAL;
3292 struct GadgetInfo *gi = level_editor_gadget[gadget_id];
3293 struct GadgetScrollbar *gs = &gi->scrollbar;
3295 if (lev_fieldy < ED_FIELDY - 2)
3299 if (level_ypos > lev_fieldy - ED_FIELDY + 1)
3300 level_ypos = lev_fieldy - ED_FIELDY + 1;
3302 ScrollMiniLevel(level_xpos, level_ypos, ED_SCROLL_UP);
3304 DrawMiniLevel(level_xpos, level_ypos);
3306 AdjustScrollbar(gi, gs->items_max, level_ypos + 1);
3310 case ED_CTRL_ID_SCROLL_HORIZONTAL:
3311 level_xpos = gi->event.item_position - 1;
3312 DrawMiniLevel(level_xpos, level_ypos);
3315 case ED_CTRL_ID_SCROLL_VERTICAL:
3316 level_ypos = gi->event.item_position - 1;
3317 DrawMiniLevel(level_xpos, level_ypos);
3320 case ED_CTRL_ID_WRAP_LEFT:
3321 WrapLevel(-step, 0);
3324 case ED_CTRL_ID_WRAP_RIGHT:
3328 case ED_CTRL_ID_WRAP_UP:
3329 WrapLevel(0, -step);
3332 case ED_CTRL_ID_WRAP_DOWN:
3336 case ED_CTRL_ID_SINGLE_ITEMS:
3337 case ED_CTRL_ID_CONNECTED_ITEMS:
3338 case ED_CTRL_ID_LINE:
3339 case ED_CTRL_ID_TEXT:
3340 case ED_CTRL_ID_RECTANGLE:
3341 case ED_CTRL_ID_FILLED_BOX:
3342 case ED_CTRL_ID_FLOOD_FILL:
3343 case ED_CTRL_ID_BRUSH:
3344 case ED_CTRL_ID_PICK_ELEMENT:
3345 last_drawing_function = drawing_function;
3346 drawing_function = id;
3349 case ED_CTRL_ID_RANDOM_PLACEMENT:
3350 RandomPlacement(button);
3353 case ED_CTRL_ID_PROPERTIES:
3354 if (edit_mode != ED_MODE_PROPERTIES)
3356 properties_element = new_element;
3357 DrawPropertiesWindow();
3358 edit_mode = ED_MODE_PROPERTIES;
3362 DrawDrawingWindow();
3363 edit_mode = ED_MODE_DRAWING;
3367 case ED_CTRL_ID_UNDO:
3368 if (undo_buffer_steps == 0)
3370 Request("Undo buffer empty !", REQ_CONFIRM);
3374 undo_buffer_position =
3375 (undo_buffer_position - 1 + NUM_UNDO_STEPS) % NUM_UNDO_STEPS;
3376 undo_buffer_steps--;
3378 for(x=0; x<lev_fieldx; x++)
3379 for(y=0; y<lev_fieldy; y++)
3380 Feld[x][y] = UndoBuffer[undo_buffer_position][x][y];
3381 DrawMiniLevel(level_xpos,level_ypos);
3384 case ED_CTRL_ID_INFO:
3385 if (edit_mode != ED_MODE_INFO)
3387 DrawControlWindow();
3388 edit_mode = ED_MODE_INFO;
3392 DrawDrawingWindow();
3393 edit_mode = ED_MODE_DRAWING;
3397 case ED_CTRL_ID_CLEAR:
3398 for(x=0; x<MAX_LEV_FIELDX; x++)
3399 for(y=0; y<MAX_LEV_FIELDY; y++)
3400 Feld[x][y] = new_element3;
3401 CopyLevelToUndoBuffer(ED_CTRL_ID_CLEAR);
3403 DrawMiniLevel(level_xpos, level_ypos);
3406 case ED_CTRL_ID_SAVE:
3407 if (leveldir[leveldir_nr].readonly)
3409 Request("This level is read only !", REQ_CONFIRM);
3413 for(y=0; y<lev_fieldy; y++)
3414 for(x=0; x<lev_fieldx; x++)
3415 if (Feld[x][y] != Ur[x][y])
3416 level_changed = TRUE;
3418 if (0 && !level_changed)
3420 Request("Level has not changed !", REQ_CONFIRM);
3424 for(y=0; y<lev_fieldy; y++)
3425 for(x=0; x<lev_fieldx; x++)
3426 if (Feld[x][y] == EL_SPIELFIGUR ||
3427 Feld[x][y] == EL_SPIELER1 ||
3428 Feld[x][y] == EL_SP_MURPHY)
3429 player_present = TRUE;
3431 if (!player_present)
3432 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
3435 if (Request("Save this level and kill the old ?", REQ_ASK))
3437 for(x=0; x<lev_fieldx; x++)
3438 for(y=0; y<lev_fieldy; y++)
3439 Ur[x][y] = Feld[x][y];
3440 SaveLevel(level_nr);
3445 case ED_CTRL_ID_TEST:
3446 for(y=0; y<lev_fieldy; y++)
3447 for(x=0; x<lev_fieldx; x++)
3448 if (Feld[x][y] == EL_SPIELFIGUR ||
3449 Feld[x][y] == EL_SPIELER1 ||
3450 Feld[x][y] == EL_SP_MURPHY)
3451 player_present = TRUE;
3453 if (!player_present)
3454 Request("No Level without Gregor Mc Duffin please !", REQ_CONFIRM);
3457 for(x=0; x<lev_fieldx; x++)
3458 for(y=0; y<lev_fieldy; y++)
3459 FieldBackup[x][y] = Ur[x][y];
3461 for(x=0; x<lev_fieldx; x++)
3462 for(y=0; y<lev_fieldy; y++)
3463 Ur[x][y] = Feld[x][y];
3465 UnmapLevelEditorGadgets();
3467 /* draw smaller door */
3468 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
3469 DOOR_GFX_PAGEX7, 64,
3472 redraw_mask |= REDRAW_ALL;
3474 CloseDoor(DOOR_CLOSE_ALL);
3476 DrawCompleteVideoDisplay();
3478 if (setup.autorecord)
3479 TapeStartRecording();
3481 level_editor_test_game = TRUE;
3482 game_status = PLAYING;
3488 case ED_CTRL_ID_EXIT:
3489 for(y=0; y<lev_fieldy; y++)
3490 for(x=0; x<lev_fieldx; x++)
3491 if (Feld[x][y] != Ur[x][y])
3492 level_changed = TRUE;
3494 if (!level_changed ||
3495 Request("Level has changed! Exit without saving ?",
3496 REQ_ASK | REQ_STAY_OPEN))
3498 CloseDoor(DOOR_CLOSE_1);
3501 CloseDoor(DOOR_CLOSE_ALL);
3504 /* draw smaller door */
3505 XCopyArea(display, pix[PIX_DOOR], drawto, gc,
3506 DOOR_GFX_PAGEX7, 64,
3509 redraw_mask |= REDRAW_ALL;
3511 game_status = MAINMENU;
3516 CloseDoor(DOOR_CLOSE_1);
3517 XCopyArea(display, pix[PIX_DB_DOOR], pix[PIX_DB_DOOR], gc,
3518 DOOR_GFX_PAGEX2, DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
3519 DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1);
3520 OpenDoor(DOOR_OPEN_1);
3526 if (gi->event.type == GD_EVENT_PRESSED)
3527 printf("default: HandleControlButtons: GD_EVENT_PRESSED\n");
3528 else if (gi->event.type == GD_EVENT_RELEASED)
3529 printf("default: HandleControlButtons: GD_EVENT_RELEASED\n");
3530 else if (gi->event.type == GD_EVENT_MOVING)
3531 printf("default: HandleControlButtons: GD_EVENT_MOVING\n");
3533 printf("default: HandleControlButtons: ?\n");
3539 void HandleLevelEditorKeyInput(KeySym key)
3541 if (edit_mode == ED_MODE_DRAWING && drawing_function == ED_CTRL_ID_TEXT)
3543 char letter = getCharFromKeySym(key);
3546 DrawLevelText(0, 0, letter, TEXT_WRITECHAR);
3547 else if (key == XK_Delete || key == XK_BackSpace)
3548 DrawLevelText(0, 0, 0, TEXT_BACKSPACE);
3549 else if (key == XK_Return)
3550 DrawLevelText(0, 0, 0, TEXT_NEWLINE);
3554 static void HandleTextInputGadgets(struct GadgetInfo *gi)
3556 int id = gi->custom_id;
3560 case ED_CTRL_ID_LEVEL_NAME:
3561 strcpy(level.name, gi->text_value);
3569 /* values for ClearEditorGadgetInfoText() and HandleGadgetInfoText() */
3570 #define INFOTEXT_XPOS SX
3571 #define INFOTEXT_YPOS (SY + SYSIZE - MINI_TILEX + 2)
3572 #define INFOTEXT_XSIZE SXSIZE
3573 #define INFOTEXT_YSIZE MINI_TILEX
3574 #define MAX_INFOTEXT_LEN (SXSIZE / FONT2_XSIZE)
3576 void ClearEditorGadgetInfoText()
3578 XFillRectangle(display, drawto, gc,
3579 INFOTEXT_XPOS, INFOTEXT_YPOS, INFOTEXT_XSIZE, INFOTEXT_YSIZE);
3580 redraw_mask |= REDRAW_FIELD;
3583 void HandleEditorGadgetInfoText(void *ptr)
3585 struct GadgetInfo *gi = (struct GadgetInfo *)ptr;
3586 char infotext[MAX_INFOTEXT_LEN + 1];
3588 ClearEditorGadgetInfoText();
3590 /* misuse this function to delete brush cursor, if needed */
3591 if (edit_mode == ED_MODE_DRAWING && draw_with_brush)
3592 DeleteBrushFromCursor();
3594 if (gi == NULL || gi->description_text == NULL)
3597 strncpy(infotext, gi->description_text, MAX_INFOTEXT_LEN);
3598 infotext[MAX_INFOTEXT_LEN] = '\0';
3600 DrawText(INFOTEXT_XPOS, INFOTEXT_YPOS, infotext, FS_SMALL, FC_YELLOW);
3603 static void HandleDrawingAreaInfo(struct GadgetInfo *gi)
3605 int id = gi->custom_id;
3606 int sx = gi->event.x;
3607 int sy = gi->event.y;
3608 int lx = sx + level_xpos;
3609 int ly = sy + level_ypos;
3611 ClearEditorGadgetInfoText();
3613 if (id == ED_CTRL_ID_DRAWING_LEVEL)
3615 if (IN_LEV_FIELD(lx, ly))
3616 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
3617 "Level: %d, %d (Screen: %d, %d)", lx, ly, sx, sy);
3619 /* misuse this function to draw brush cursor, if needed */
3620 if (edit_mode == ED_MODE_DRAWING && draw_with_brush)
3621 CopyBrushToCursor(sx, sy);
3623 else if (id == ED_CTRL_ID_AMOEBA_CONTENT)
3624 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
3627 DrawTextF(INFOTEXT_XPOS - SX, INFOTEXT_YPOS - SY, FC_YELLOW,
3628 "Cruncher %d content: %d, %d", id - ED_CTRL_ID_ELEMCONT_0 + 1,